]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <html> |
2 | <head> | |
3 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
4 | <title>Class pooled_fixedsize_stack</title> | |
5 | <link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> | |
6 | <meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> | |
7 | <link rel="home" href="../../../index.html" title="Chapter 1. Fiber"> | |
8 | <link rel="up" href="../protected_fixedsize.html" title="Class protected_fixedsize_stack"> | |
9 | <link rel="prev" href="../protected_fixedsize.html" title="Class protected_fixedsize_stack"> | |
10 | </head> | |
11 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | |
12 | <table cellpadding="2" width="100%"><tr> | |
13 | <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> | |
14 | <td align="center"><a href="../../../../../../../index.html">Home</a></td> | |
15 | <td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td> | |
16 | <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> | |
17 | <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> | |
18 | <td align="center"><a href="../../../../../../../more/index.htm">More</a></td> | |
19 | </tr></table> | |
20 | <hr> | |
21 | <div class="spirit-nav"> | |
22 | <a accesskey="p" href="../protected_fixedsize.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../protected_fixedsize.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a> | |
23 | </div> | |
24 | <div class="section"> | |
25 | <div class="titlepage"><div><div><h4 class="title"> | |
26 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize"></a><a class="link" href="pooled_fixedsize.html" title="Class pooled_fixedsize_stack">Class | |
27 | <span class="emphasis"><em>pooled_fixedsize_stack</em></span></a> | |
28 | </h4></div></div></div> | |
29 | <div class="toc"><dl> | |
30 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fixedsize">Class | |
31 | <span class="emphasis"><em>fixedsize_stack</em></span></a></span></dt> | |
32 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.segmented_stack">Class | |
33 | <span class="emphasis"><em>segmented_stack</em></span></a></span></dt> | |
34 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization">Synchronization</a></span></dt> | |
35 | <dd><dl> | |
36 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.mutex_types">Mutex | |
37 | Types</a></span></dt> | |
38 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions">Condition | |
39 | Variables</a></span></dt> | |
40 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers">Barriers</a></span></dt> | |
41 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels">Channels</a></span></dt> | |
42 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures">Futures</a></span></dt> | |
43 | <dd><dl> | |
44 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future">Future</a></span></dt> | |
45 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise">Template | |
46 | <code class="computeroutput"><span class="identifier">promise</span><span class="special"><></span></code></a></span></dt> | |
47 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task">Template | |
48 | <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code></a></span></dt> | |
49 | </dl></dd> | |
50 | </dl></dd> | |
51 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fls">Fiber | |
52 | local storage</a></span></dt> | |
53 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration">Migrating | |
54 | fibers between threads</a></span></dt> | |
55 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks">Integrating | |
56 | Fibers with Asynchronous Callbacks</a></span></dt> | |
57 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking">Integrating | |
58 | Fibers with Nonblocking I/O</a></span></dt> | |
59 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any">when_any | |
60 | / when_all functionality</a></span></dt> | |
61 | <dd><dl> | |
62 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any">when_any</a></span></dt> | |
63 | <dd><dl> | |
64 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__simple_completion">when_any, | |
65 | simple completion</a></span></dt> | |
66 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__return_value">when_any, | |
67 | return value</a></span></dt> | |
68 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">when_any, | |
69 | produce first outcome, whether result or exception</a></span></dt> | |
70 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_success">when_any, | |
71 | produce first success</a></span></dt> | |
72 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__heterogeneous_types">when_any, | |
73 | heterogeneous types</a></span></dt> | |
74 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__a_dubious_alternative">when_any, | |
75 | a dubious alternative</a></span></dt> | |
76 | </dl></dd> | |
77 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality">when_all | |
78 | functionality</a></span></dt> | |
79 | <dd><dl> | |
80 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__simple_completion">when_all, | |
81 | simple completion</a></span></dt> | |
82 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__return_values">when_all, | |
83 | return values</a></span></dt> | |
84 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all_until_first_exception">when_all | |
85 | until first exception</a></span></dt> | |
86 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.wait_all__collecting_all_exceptions">wait_all, | |
87 | collecting all exceptions</a></span></dt> | |
88 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__heterogeneous_types">when_all, | |
89 | heterogeneous types</a></span></dt> | |
90 | </dl></dd> | |
91 | </dl></dd> | |
92 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.integration">Sharing | |
93 | a Thread with Another Main Loop</a></span></dt> | |
94 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.performance">Performance</a></span></dt> | |
95 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom">Customization</a></span></dt> | |
96 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale">Rationale</a></span></dt> | |
97 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.acknowledgements">Acknowledgments</a></span></dt> | |
98 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.installing">Appendix: | |
99 | Installing and Running Tests</a></span></dt> | |
100 | </dl></div> | |
101 | <p> | |
102 | <span class="bold"><strong>Boost.Fiber</strong></span> provides the class <a class="link" href="../../../"> <code class="computeroutput">pooled_fixedsize_stack</code></a> which | |
103 | models the <a class="link" href="../../stack.html#stack_allocator_concept"><span class="emphasis"><em>stack-allocator | |
104 | concept</em></span></a>. In contrast to <a class="link" href="../../../"> <code class="computeroutput">protected_fixedsize_stack</code></a> it | |
105 | does not append a guard page at the end of each stack. The memory is managed | |
106 | internally by <a href="http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">pool</span><span class="special"><></span></code></a>. | |
107 | </p> | |
108 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">pooled_fixedsize_stack</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
109 | ||
110 | <span class="keyword">struct</span> <span class="identifier">pooled_fixedsize_stack</span> <span class="special">{</span> | |
111 | <span class="identifier">pooled_fixedsize_stack</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">stack_size</span> <span class="special">=</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">default_size</span><span class="special">(),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">next_size</span> <span class="special">=</span> <span class="number">32</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">max_size</span> <span class="special">=</span> <span class="number">0</span><span class="special">);</span> | |
112 | ||
113 | <span class="identifier">stack_context</span> <span class="identifier">allocate</span><span class="special">();</span> | |
114 | ||
115 | <span class="keyword">void</span> <span class="identifier">deallocate</span><span class="special">(</span> <span class="identifier">stack_context</span> <span class="special">&);</span> | |
116 | <span class="special">}</span> | |
117 | </pre> | |
118 | <h6> | |
119 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.h0"></a> | |
120 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize._code__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___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize._code__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___code_"><code class="computeroutput"><span class="identifier">pooled_fixedsize_stack</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">stack_size</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">next_size</span><span class="special">,</span> | |
121 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">max_size</span><span class="special">)</span></code></a> | |
122 | </h6> | |
123 | <div class="variablelist"> | |
124 | <p class="title"><b></b></p> | |
125 | <dl> | |
126 | <dt><span class="term">Preconditions:</span></dt> | |
127 | <dd><p> | |
128 | <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">is_unbounded</span><span class="special">()</span> | |
129 | <span class="special">||</span> <span class="special">(</span> | |
130 | <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">maximum_size</span><span class="special">()</span> | |
131 | <span class="special">>=</span> <span class="identifier">stack_size</span><span class="special">)</span></code> and <code class="computeroutput"><span class="number">0</span> | |
132 | <span class="special"><</span> <span class="identifier">next_size</span></code>. | |
133 | </p></dd> | |
134 | <dt><span class="term">Effects:</span></dt> | |
135 | <dd><p> | |
136 | Allocates memory of at least <code class="computeroutput"><span class="identifier">stack_size</span></code> | |
137 | bytes and stores a pointer to the stack and its actual size in <code class="computeroutput"><span class="identifier">sctx</span></code>. Depending on the architecture | |
138 | (the stack grows downwards/upwards) the stored address is the highest/lowest | |
139 | address of the stack. Argument <code class="computeroutput"><span class="identifier">next_size</span></code> | |
140 | determines the number of stacks to request from the system the first | |
141 | time that <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
142 | needs to allocate system memory. The third argument <code class="computeroutput"><span class="identifier">max_size</span></code> controls how much memory | |
143 | might be allocated for stacks — a value of zero means no upper limit. | |
144 | </p></dd> | |
145 | </dl> | |
146 | </div> | |
147 | <h6> | |
148 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.h1"></a> | |
149 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"><code class="computeroutput"><span class="identifier">stack_context</span> <span class="identifier">allocate</span><span class="special">()</span></code></a> | |
150 | </h6> | |
151 | <div class="variablelist"> | |
152 | <p class="title"><b></b></p> | |
153 | <dl> | |
154 | <dt><span class="term">Preconditions:</span></dt> | |
155 | <dd><p> | |
156 | <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">is_unbounded</span><span class="special">()</span> | |
157 | <span class="special">||</span> <span class="special">(</span> | |
158 | <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">maximum_size</span><span class="special">()</span> | |
159 | <span class="special">>=</span> <span class="identifier">stack_size</span><span class="special">)</span></code>. | |
160 | </p></dd> | |
161 | <dt><span class="term">Effects:</span></dt> | |
162 | <dd><p> | |
163 | Allocates memory of at least <code class="computeroutput"><span class="identifier">stack_size</span></code> | |
164 | bytes and stores a pointer to the stack and its actual size in <code class="computeroutput"><span class="identifier">sctx</span></code>. Depending on the architecture | |
165 | (the stack grows downwards/upwards) the stored address is the highest/lowest | |
166 | address of the stack. | |
167 | </p></dd> | |
168 | </dl> | |
169 | </div> | |
170 | <h6> | |
171 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.h2"></a> | |
172 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"><code class="computeroutput"><span class="keyword">void</span> <span class="identifier">deallocate</span><span class="special">(</span> <span class="identifier">stack_context</span> | |
173 | <span class="special">&</span> <span class="identifier">sctx</span><span class="special">)</span></code></a> | |
174 | </h6> | |
175 | <div class="variablelist"> | |
176 | <p class="title"><b></b></p> | |
177 | <dl> | |
178 | <dt><span class="term">Preconditions:</span></dt> | |
179 | <dd><p> | |
180 | <code class="computeroutput"><span class="identifier">sctx</span><span class="special">.</span><span class="identifier">sp</span></code> is valid, <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">is_unbounded</span><span class="special">()</span> <span class="special">||</span> <span class="special">(</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">maximum_size</span><span class="special">()</span> <span class="special">>=</span> | |
181 | <span class="identifier">sctx</span><span class="special">.</span><span class="identifier">size</span><span class="special">)</span></code>. | |
182 | </p></dd> | |
183 | <dt><span class="term">Effects:</span></dt> | |
184 | <dd><p> | |
185 | Deallocates the stack space. | |
186 | </p></dd> | |
187 | </dl> | |
188 | </div> | |
189 | <div class="section"> | |
190 | <div class="titlepage"><div><div><h5 class="title"> | |
191 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fixedsize"></a><a name="class_fixedsize_stack"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fixedsize" title="Class fixedsize_stack">Class | |
192 | <span class="emphasis"><em>fixedsize_stack</em></span></a> | |
193 | </h5></div></div></div> | |
194 | <p> | |
195 | <span class="bold"><strong>Boost.Fiber</strong></span> provides the class __fixedsize__ | |
196 | which models the <a class="link" href="../../stack.html#stack_allocator_concept"><span class="emphasis"><em>stack-allocator | |
197 | concept</em></span></a>. In contrast to __protected_fixedsize__ it | |
198 | does not append a guard page at the end of each stack. The memory is | |
199 | simply managed by <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">malloc</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">free</span><span class="special">()</span></code>. | |
200 | </p> | |
201 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">context</span><span class="special">/</span><span class="identifier">fixedsize_stack</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
202 | ||
203 | <span class="keyword">struct</span> <span class="identifier">fixedsize_stack</span> <span class="special">{</span> | |
204 | <span class="identifier">fixedsize_stack</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">size</span> <span class="special">=</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">default_size</span><span class="special">());</span> | |
205 | ||
206 | <span class="identifier">stack_context</span> <span class="identifier">allocate</span><span class="special">();</span> | |
207 | ||
208 | <span class="keyword">void</span> <span class="identifier">deallocate</span><span class="special">(</span> <span class="identifier">stack_context</span> <span class="special">&);</span> | |
209 | <span class="special">}</span> | |
210 | </pre> | |
211 | <h6> | |
212 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fixedsize.h0"></a> | |
213 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fixedsize._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"><code class="computeroutput"><span class="identifier">stack_context</span> <span class="identifier">allocate</span><span class="special">()</span></code></a> | |
214 | </h6> | |
215 | <div class="variablelist"> | |
216 | <p class="title"><b></b></p> | |
217 | <dl> | |
218 | <dt><span class="term">Preconditions:</span></dt> | |
219 | <dd><p> | |
220 | <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">minimum_size</span><span class="special">()</span> | |
221 | <span class="special"><=</span> <span class="identifier">size</span></code> | |
222 | and <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">is_unbounded</span><span class="special">()</span> <span class="special">||</span> | |
223 | <span class="special">(</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">maximum_size</span><span class="special">()</span> <span class="special">>=</span> | |
224 | <span class="identifier">size</span><span class="special">)</span></code>. | |
225 | </p></dd> | |
226 | <dt><span class="term">Effects:</span></dt> | |
227 | <dd><p> | |
228 | Allocates memory of at least <code class="computeroutput"><span class="identifier">size</span></code> | |
229 | bytes and stores a pointer to the stack and its actual size in | |
230 | <code class="computeroutput"><span class="identifier">sctx</span></code>. Depending | |
231 | on the architecture (the stack grows downwards/upwards) the stored | |
232 | address is the highest/lowest address of the stack. | |
233 | </p></dd> | |
234 | </dl> | |
235 | </div> | |
236 | <h6> | |
237 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fixedsize.h1"></a> | |
238 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fixedsize._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"><code class="computeroutput"><span class="keyword">void</span> <span class="identifier">deallocate</span><span class="special">(</span> <span class="identifier">stack_context</span> | |
239 | <span class="special">&</span> <span class="identifier">sctx</span><span class="special">)</span></code></a> | |
240 | </h6> | |
241 | <div class="variablelist"> | |
242 | <p class="title"><b></b></p> | |
243 | <dl> | |
244 | <dt><span class="term">Preconditions:</span></dt> | |
245 | <dd><p> | |
246 | <code class="computeroutput"><span class="identifier">sctx</span><span class="special">.</span><span class="identifier">sp</span></code> is valid, <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">minimum_size</span><span class="special">()</span> <span class="special"><=</span> | |
247 | <span class="identifier">sctx</span><span class="special">.</span><span class="identifier">size</span></code> and <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">is_unbounded</span><span class="special">()</span> <span class="special">||</span> | |
248 | <span class="special">(</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">maximum_size</span><span class="special">()</span> <span class="special">>=</span> | |
249 | <span class="identifier">sctx</span><span class="special">.</span><span class="identifier">size</span><span class="special">)</span></code>. | |
250 | </p></dd> | |
251 | <dt><span class="term">Effects:</span></dt> | |
252 | <dd><p> | |
253 | Deallocates the stack space. | |
254 | </p></dd> | |
255 | </dl> | |
256 | </div> | |
257 | </div> | |
258 | <div class="section"> | |
259 | <div class="titlepage"><div><div><h5 class="title"> | |
260 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.segmented_stack"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.segmented_stack" title="Class segmented_stack">Class | |
261 | <span class="emphasis"><em>segmented_stack</em></span></a> | |
262 | </h5></div></div></div> | |
263 | <p> | |
264 | <span class="bold"><strong>Boost.Fiber</strong></span> supports usage of a <a class="link" href="../../../"> <code class="computeroutput">segmented_stack</code></a>, | |
265 | i.e. the stack grows on demand. The fiber is created with a minimal stack | |
266 | size which will be increased as required. Class <a class="link" href="../../../"> <code class="computeroutput">segmented_stack</code></a> models | |
267 | the <a class="link" href="../../stack.html#stack_allocator_concept"><span class="emphasis"><em>stack-allocator | |
268 | concept</em></span></a>. In contrast to <a class="link" href="../../../"> <code class="computeroutput">protected_fixedsize_stack</code></a> and | |
269 | <a class="link" href="pooled_fixedsize.html#class_fixedsize_stack"> <code class="computeroutput">fixedsize_stack</code></a> it creates a stack which grows on | |
270 | demand. | |
271 | </p> | |
272 | <div class="note"><table border="0" summary="Note"> | |
273 | <tr> | |
274 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> | |
275 | <th align="left">Note</th> | |
276 | </tr> | |
277 | <tr><td align="left" valign="top"><p> | |
278 | Segmented stacks are currently only supported by <span class="bold"><strong>gcc</strong></span> | |
279 | from version <span class="bold"><strong>4.7</strong></span> and <span class="bold"><strong>clang</strong></span> | |
280 | from version <span class="bold"><strong>3.4</strong></span> onwards. In order | |
281 | to use a <a class="link" href="../../../"> <code class="computeroutput">segmented_stack</code></a> <span class="bold"><strong>Boost.Fiber</strong></span> | |
282 | must be built with property <code class="computeroutput"><span class="identifier">segmented</span><span class="special">-</span><span class="identifier">stacks</span></code>, | |
283 | e.g. <span class="bold"><strong>toolset=gcc segmented-stacks=on</strong></span> | |
284 | at b2/bjam command line. | |
285 | </p></td></tr> | |
286 | </table></div> | |
287 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">segmented_stack</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
288 | ||
289 | <span class="keyword">struct</span> <span class="identifier">segmented_stack</span> <span class="special">{</span> | |
290 | <span class="identifier">segmented_stack</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">stack_size</span> <span class="special">=</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">default_size</span><span class="special">());</span> | |
291 | ||
292 | <span class="identifier">stack_context</span> <span class="identifier">allocate</span><span class="special">();</span> | |
293 | ||
294 | <span class="keyword">void</span> <span class="identifier">deallocate</span><span class="special">(</span> <span class="identifier">stack_context</span> <span class="special">&);</span> | |
295 | <span class="special">}</span> | |
296 | </pre> | |
297 | <h6> | |
298 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.segmented_stack.h0"></a> | |
299 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.segmented_stack._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.segmented_stack._code__phrase_role__identifier__stack_context__phrase___phrase_role__identifier__allocate__phrase__phrase_role__special______phrase___code_"><code class="computeroutput"><span class="identifier">stack_context</span> <span class="identifier">allocate</span><span class="special">()</span></code></a> | |
300 | </h6> | |
301 | <div class="variablelist"> | |
302 | <p class="title"><b></b></p> | |
303 | <dl> | |
304 | <dt><span class="term">Preconditions:</span></dt> | |
305 | <dd><p> | |
306 | <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">minimum_size</span><span class="special">()</span> | |
307 | <span class="special"><=</span> <span class="identifier">size</span></code> | |
308 | and <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">is_unbounded</span><span class="special">()</span> <span class="special">||</span> | |
309 | <span class="special">(</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">maximum_size</span><span class="special">()</span> <span class="special">>=</span> | |
310 | <span class="identifier">size</span><span class="special">)</span></code>. | |
311 | </p></dd> | |
312 | <dt><span class="term">Effects:</span></dt> | |
313 | <dd><p> | |
314 | Allocates memory of at least <code class="computeroutput"><span class="identifier">size</span></code> | |
315 | bytes and stores a pointer to the stack and its actual size in | |
316 | <code class="computeroutput"><span class="identifier">sctx</span></code>. Depending | |
317 | on the architecture (the stack grows downwards/upwards) the stored | |
318 | address is the highest/lowest address of the stack. | |
319 | </p></dd> | |
320 | </dl> | |
321 | </div> | |
322 | <h6> | |
323 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.segmented_stack.h1"></a> | |
324 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.segmented_stack._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.segmented_stack._code__phrase_role__keyword__void__phrase___phrase_role__identifier__deallocate__phrase__phrase_role__special_____phrase___phrase_role__identifier__stack_context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__sctx__phrase__phrase_role__special_____phrase___code_"><code class="computeroutput"><span class="keyword">void</span> <span class="identifier">deallocate</span><span class="special">(</span> <span class="identifier">stack_context</span> | |
325 | <span class="special">&</span> <span class="identifier">sctx</span><span class="special">)</span></code></a> | |
326 | </h6> | |
327 | <div class="variablelist"> | |
328 | <p class="title"><b></b></p> | |
329 | <dl> | |
330 | <dt><span class="term">Preconditions:</span></dt> | |
331 | <dd><p> | |
332 | <code class="computeroutput"><span class="identifier">sctx</span><span class="special">.</span><span class="identifier">sp</span></code> is valid, <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">minimum_size</span><span class="special">()</span> <span class="special"><=</span> | |
333 | <span class="identifier">sctx</span><span class="special">.</span><span class="identifier">size</span></code> and <code class="computeroutput"><span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">is_unbounded</span><span class="special">()</span> <span class="special">||</span> | |
334 | <span class="special">(</span> <span class="identifier">traits_type</span><span class="special">::</span><span class="identifier">maximum_size</span><span class="special">()</span> <span class="special">>=</span> | |
335 | <span class="identifier">sctx</span><span class="special">.</span><span class="identifier">size</span><span class="special">)</span></code>. | |
336 | </p></dd> | |
337 | <dt><span class="term">Effects:</span></dt> | |
338 | <dd><p> | |
339 | Deallocates the stack space. | |
340 | </p></dd> | |
341 | </dl> | |
342 | </div> | |
343 | <div class="note"><table border="0" summary="Note"> | |
344 | <tr> | |
345 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> | |
346 | <th align="left">Note</th> | |
347 | </tr> | |
348 | <tr><td align="left" valign="top"><p> | |
349 | If the library is compiled for segmented stacks, <a class="link" href="../../../"> <code class="computeroutput">segmented_stack</code></a> is | |
350 | the only available stack allocator. | |
351 | </p></td></tr> | |
352 | </table></div> | |
353 | </div> | |
354 | <div class="section"> | |
355 | <div class="titlepage"><div><div><h5 class="title"> | |
356 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization"></a><a name="synchronization"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization" title="Synchronization">Synchronization</a> | |
357 | </h5></div></div></div> | |
358 | <div class="toc"><dl> | |
359 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.mutex_types">Mutex | |
360 | Types</a></span></dt> | |
361 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions">Condition | |
362 | Variables</a></span></dt> | |
363 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers">Barriers</a></span></dt> | |
364 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels">Channels</a></span></dt> | |
365 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures">Futures</a></span></dt> | |
366 | <dd><dl> | |
367 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future">Future</a></span></dt> | |
368 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise">Template | |
369 | <code class="computeroutput"><span class="identifier">promise</span><span class="special"><></span></code></a></span></dt> | |
370 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task">Template | |
371 | <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code></a></span></dt> | |
372 | </dl></dd> | |
373 | </dl></div> | |
374 | <p> | |
375 | In general, <span class="bold"><strong>Boost.Fiber</strong></span> synchronization | |
376 | objects can neither be moved nor copied. A synchronization object acts | |
377 | as a mutually-agreed rendezvous point between different fibers. If such | |
378 | an object were copied somewhere else, the new copy would have no consumers. | |
379 | If such an object were <span class="emphasis"><em>moved</em></span> somewhere else, leaving | |
380 | the original instance in an unspecified state, existing consumers would | |
381 | behave strangely. | |
382 | </p> | |
383 | <p> | |
384 | The fiber synchronization objects provided by this library will, by default, | |
385 | safely synchronize fibers running on different threads. However, this | |
386 | level of synchronization can be removed (for performance) by building | |
387 | the library with <span class="bold"><strong><code class="computeroutput"><span class="identifier">BOOST_FIBERS_NO_ATOMICS</span></code></strong></span> | |
388 | defined. When the library is built with that macro, you must ensure that | |
389 | all the fibers referencing a particular synchronization object are running | |
390 | in the same thread. | |
391 | </p> | |
392 | <div class="section"> | |
393 | <div class="titlepage"><div><div><h6 class="title"> | |
394 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.mutex_types"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.mutex_types" title="Mutex Types">Mutex | |
395 | Types</a> | |
396 | </h6></div></div></div> | |
397 | <p> | |
398 | </p> | |
399 | <h5> | |
400 | <a name="class_mutex_bridgehead"></a> | |
401 | <span><a name="class_mutex"></a></span> | |
402 | <a class="link" href="pooled_fixedsize.html#class_mutex">Class <code class="computeroutput">mutex</code></a> | |
403 | </h5> | |
404 | <p> | |
405 | </p> | |
406 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
407 | ||
408 | <span class="keyword">class</span> <span class="identifier">mutex</span> <span class="special">{</span> | |
409 | <span class="keyword">public</span><span class="special">:</span> | |
410 | <span class="identifier">mutex</span><span class="special">();</span> | |
411 | <span class="special">~</span><span class="identifier">mutex</span><span class="special">();</span> | |
412 | ||
413 | <span class="identifier">mutex</span><span class="special">(</span> <span class="identifier">mutex</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
414 | <span class="identifier">mutex</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">mutex</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
415 | ||
416 | <span class="keyword">void</span> <span class="identifier">lock</span><span class="special">();</span> | |
417 | <span class="keyword">bool</span> <span class="identifier">try_lock</span><span class="special">();</span> | |
418 | <span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">();</span> | |
419 | <span class="special">};</span> | |
420 | </pre> | |
421 | <p> | |
422 | <a class="link" href="pooled_fixedsize.html#class_mutex"> <code class="computeroutput">mutex</code></a> provides an exclusive-ownership mutex. At most one | |
423 | fiber can own the lock on a given instance of <a class="link" href="pooled_fixedsize.html#class_mutex"> <code class="computeroutput">mutex</code></a> at any | |
424 | time. Multiple concurrent calls to <code class="computeroutput"><span class="identifier">lock</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">try_lock</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">unlock</span><span class="special">()</span></code> shall be permitted. | |
425 | </p> | |
426 | <p> | |
427 | Any fiber blocked in <code class="computeroutput"><span class="identifier">lock</span><span class="special">()</span></code> is suspended until the owning fiber | |
428 | releases the lock by calling <code class="computeroutput"><span class="identifier">unlock</span><span class="special">()</span></code>. | |
429 | </p> | |
430 | <p> | |
431 | </p> | |
432 | <h5> | |
433 | <a name="mutex_lock_bridgehead"></a> | |
434 | <span><a name="mutex_lock"></a></span> | |
435 | <a class="link" href="pooled_fixedsize.html#mutex_lock">Member function <code class="computeroutput">lock</code>()</a> | |
436 | </h5> | |
437 | <p> | |
438 | </p> | |
439 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">lock</span><span class="special">();</span> | |
440 | </pre> | |
441 | <div class="variablelist"> | |
442 | <p class="title"><b></b></p> | |
443 | <dl> | |
444 | <dt><span class="term">Precondition:</span></dt> | |
445 | <dd><p> | |
446 | The calling fiber doesn't own the mutex. | |
447 | </p></dd> | |
448 | <dt><span class="term">Effects:</span></dt> | |
449 | <dd><p> | |
450 | The current fiber blocks until ownership can be obtained. | |
451 | </p></dd> | |
452 | <dt><span class="term">Throws:</span></dt> | |
453 | <dd><p> | |
454 | <code class="computeroutput"><span class="identifier">lock_error</span></code> | |
455 | </p></dd> | |
456 | <dt><span class="term">Error Conditions:</span></dt> | |
457 | <dd><p> | |
458 | <span class="bold"><strong>resource_deadlock_would_occur</strong></span>: | |
459 | if <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
460 | already owns the mutex. | |
461 | </p></dd> | |
462 | </dl> | |
463 | </div> | |
464 | <p> | |
465 | </p> | |
466 | <h5> | |
467 | <a name="mutex_try_lock_bridgehead"></a> | |
468 | <span><a name="mutex_try_lock"></a></span> | |
469 | <a class="link" href="pooled_fixedsize.html#mutex_try_lock">Member function | |
470 | <code class="computeroutput">try_lock</code>()</a> | |
471 | </h5> | |
472 | <p> | |
473 | </p> | |
474 | <pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">try_lock</span><span class="special">();</span> | |
475 | </pre> | |
476 | <div class="variablelist"> | |
477 | <p class="title"><b></b></p> | |
478 | <dl> | |
479 | <dt><span class="term">Precondition:</span></dt> | |
480 | <dd><p> | |
481 | The calling fiber doesn't own the mutex. | |
482 | </p></dd> | |
483 | <dt><span class="term">Effects:</span></dt> | |
484 | <dd><p> | |
485 | Attempt to obtain ownership for the current fiber without blocking. | |
486 | </p></dd> | |
487 | <dt><span class="term">Returns:</span></dt> | |
488 | <dd><p> | |
489 | <code class="computeroutput"><span class="keyword">true</span></code> if ownership | |
490 | was obtained for the current fiber, <code class="computeroutput"><span class="keyword">false</span></code> | |
491 | otherwise. | |
492 | </p></dd> | |
493 | <dt><span class="term">Throws:</span></dt> | |
494 | <dd><p> | |
495 | <code class="computeroutput"><span class="identifier">lock_error</span></code> | |
496 | </p></dd> | |
497 | <dt><span class="term">Error Conditions:</span></dt> | |
498 | <dd><p> | |
499 | <span class="bold"><strong>resource_deadlock_would_occur</strong></span>: | |
500 | if <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
501 | already owns the mutex. | |
502 | </p></dd> | |
503 | </dl> | |
504 | </div> | |
505 | <p> | |
506 | </p> | |
507 | <h5> | |
508 | <a name="mutex_unlock_bridgehead"></a> | |
509 | <span><a name="mutex_unlock"></a></span> | |
510 | <a class="link" href="pooled_fixedsize.html#mutex_unlock">Member function <code class="computeroutput">unlock</code>()</a> | |
511 | </h5> | |
512 | <p> | |
513 | </p> | |
514 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">();</span> | |
515 | </pre> | |
516 | <div class="variablelist"> | |
517 | <p class="title"><b></b></p> | |
518 | <dl> | |
519 | <dt><span class="term">Precondition:</span></dt> | |
520 | <dd><p> | |
521 | The current fiber owns <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. | |
522 | </p></dd> | |
523 | <dt><span class="term">Effects:</span></dt> | |
524 | <dd><p> | |
525 | Releases a lock on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by the current fiber. | |
526 | </p></dd> | |
527 | <dt><span class="term">Throws:</span></dt> | |
528 | <dd><p> | |
529 | <code class="computeroutput"><span class="identifier">lock_error</span></code> | |
530 | </p></dd> | |
531 | <dt><span class="term">Error Conditions:</span></dt> | |
532 | <dd><p> | |
533 | <span class="bold"><strong>operation_not_permitted</strong></span>: if | |
534 | <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
535 | does not own the mutex. | |
536 | </p></dd> | |
537 | </dl> | |
538 | </div> | |
539 | <p> | |
540 | </p> | |
541 | <h5> | |
542 | <a name="class_timed_mutex_bridgehead"></a> | |
543 | <span><a name="class_timed_mutex"></a></span> | |
544 | <a class="link" href="pooled_fixedsize.html#class_timed_mutex">Class | |
545 | <code class="computeroutput">timed_mutex</code></a> | |
546 | </h5> | |
547 | <p> | |
548 | </p> | |
549 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">timed_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
550 | ||
551 | <span class="keyword">class</span> <span class="identifier">timed_mutex</span> <span class="special">{</span> | |
552 | <span class="keyword">public</span><span class="special">:</span> | |
553 | <span class="identifier">timed_mutex</span><span class="special">();</span> | |
554 | <span class="special">~</span><span class="identifier">timed_mutex</span><span class="special">();</span> | |
555 | ||
556 | <span class="identifier">timed_mutex</span><span class="special">(</span> <span class="identifier">timed_mutex</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
557 | <span class="identifier">timed_mutex</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">timed_mutex</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
558 | ||
559 | <span class="keyword">void</span> <span class="identifier">lock</span><span class="special">();</span> | |
560 | <span class="keyword">bool</span> <span class="identifier">try_lock</span><span class="special">();</span> | |
561 | <span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">();</span> | |
562 | ||
563 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
564 | <span class="keyword">bool</span> <span class="identifier">try_lock_until</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
565 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
566 | <span class="keyword">bool</span> <span class="identifier">try_lock_for</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
567 | <span class="special">};</span> | |
568 | </pre> | |
569 | <p> | |
570 | <a class="link" href="pooled_fixedsize.html#class_timed_mutex"> <code class="computeroutput">timed_mutex</code></a> provides an exclusive-ownership mutex. | |
571 | At most one fiber can own the lock on a given instance of <a class="link" href="pooled_fixedsize.html#class_timed_mutex"> <code class="computeroutput">timed_mutex</code></a> at | |
572 | any time. Multiple concurrent calls to <code class="computeroutput"><span class="identifier">lock</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">try_lock</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">try_lock_until</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">try_lock_for</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">unlock</span><span class="special">()</span></code> shall be permitted. | |
573 | </p> | |
574 | <p> | |
575 | </p> | |
576 | <h5> | |
577 | <a name="timed_mutex_lock_bridgehead"></a> | |
578 | <span><a name="timed_mutex_lock"></a></span> | |
579 | <a class="link" href="pooled_fixedsize.html#timed_mutex_lock">Member function | |
580 | <code class="computeroutput">lock</code>()</a> | |
581 | </h5> | |
582 | <p> | |
583 | </p> | |
584 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">lock</span><span class="special">();</span> | |
585 | </pre> | |
586 | <div class="variablelist"> | |
587 | <p class="title"><b></b></p> | |
588 | <dl> | |
589 | <dt><span class="term">Precondition:</span></dt> | |
590 | <dd><p> | |
591 | The calling fiber doesn't own the mutex. | |
592 | </p></dd> | |
593 | <dt><span class="term">Effects:</span></dt> | |
594 | <dd><p> | |
595 | The current fiber blocks until ownership can be obtained. | |
596 | </p></dd> | |
597 | <dt><span class="term">Throws:</span></dt> | |
598 | <dd><p> | |
599 | <code class="computeroutput"><span class="identifier">lock_error</span></code> | |
600 | </p></dd> | |
601 | <dt><span class="term">Error Conditions:</span></dt> | |
602 | <dd><p> | |
603 | <span class="bold"><strong>resource_deadlock_would_occur</strong></span>: | |
604 | if <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
605 | already owns the mutex. | |
606 | </p></dd> | |
607 | </dl> | |
608 | </div> | |
609 | <p> | |
610 | </p> | |
611 | <h5> | |
612 | <a name="timed_mutex_try_lock_bridgehead"></a> | |
613 | <span><a name="timed_mutex_try_lock"></a></span> | |
614 | <a class="link" href="pooled_fixedsize.html#timed_mutex_try_lock">Member | |
615 | function <code class="computeroutput">try_lock</code>()</a> | |
616 | </h5> | |
617 | <p> | |
618 | </p> | |
619 | <pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">try_lock</span><span class="special">();</span> | |
620 | </pre> | |
621 | <div class="variablelist"> | |
622 | <p class="title"><b></b></p> | |
623 | <dl> | |
624 | <dt><span class="term">Precondition:</span></dt> | |
625 | <dd><p> | |
626 | The calling fiber doesn't own the mutex. | |
627 | </p></dd> | |
628 | <dt><span class="term">Effects:</span></dt> | |
629 | <dd><p> | |
630 | Attempt to obtain ownership for the current fiber without blocking. | |
631 | </p></dd> | |
632 | <dt><span class="term">Returns:</span></dt> | |
633 | <dd><p> | |
634 | <code class="computeroutput"><span class="keyword">true</span></code> if ownership | |
635 | was obtained for the current fiber, <code class="computeroutput"><span class="keyword">false</span></code> | |
636 | otherwise. | |
637 | </p></dd> | |
638 | <dt><span class="term">Throws:</span></dt> | |
639 | <dd><p> | |
640 | <code class="computeroutput"><span class="identifier">lock_error</span></code> | |
641 | </p></dd> | |
642 | <dt><span class="term">Error Conditions:</span></dt> | |
643 | <dd><p> | |
644 | <span class="bold"><strong>resource_deadlock_would_occur</strong></span>: | |
645 | if <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
646 | already owns the mutex. | |
647 | </p></dd> | |
648 | </dl> | |
649 | </div> | |
650 | <p> | |
651 | </p> | |
652 | <h5> | |
653 | <a name="timed_mutex_unlock_bridgehead"></a> | |
654 | <span><a name="timed_mutex_unlock"></a></span> | |
655 | <a class="link" href="pooled_fixedsize.html#timed_mutex_unlock">Member | |
656 | function <code class="computeroutput">unlock</code>()</a> | |
657 | </h5> | |
658 | <p> | |
659 | </p> | |
660 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">();</span> | |
661 | </pre> | |
662 | <div class="variablelist"> | |
663 | <p class="title"><b></b></p> | |
664 | <dl> | |
665 | <dt><span class="term">Precondition:</span></dt> | |
666 | <dd><p> | |
667 | The current fiber owns <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. | |
668 | </p></dd> | |
669 | <dt><span class="term">Effects:</span></dt> | |
670 | <dd><p> | |
671 | Releases a lock on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by the current fiber. | |
672 | </p></dd> | |
673 | <dt><span class="term">Throws:</span></dt> | |
674 | <dd><p> | |
675 | <code class="computeroutput"><span class="identifier">lock_error</span></code> | |
676 | </p></dd> | |
677 | <dt><span class="term">Error Conditions:</span></dt> | |
678 | <dd><p> | |
679 | <span class="bold"><strong>operation_not_permitted</strong></span>: if | |
680 | <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
681 | does not own the mutex. | |
682 | </p></dd> | |
683 | </dl> | |
684 | </div> | |
685 | <p> | |
686 | </p> | |
687 | <h5> | |
688 | <a name="timed_mutex_try_lock_until_bridgehead"></a> | |
689 | <span><a name="timed_mutex_try_lock_until"></a></span> | |
690 | <a class="link" href="pooled_fixedsize.html#timed_mutex_try_lock_until">Templated | |
691 | member function <code class="computeroutput">try_lock_until</code>()</a> | |
692 | </h5> | |
693 | <p> | |
694 | </p> | |
695 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
696 | <span class="keyword">bool</span> <span class="identifier">try_lock_until</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
697 | </pre> | |
698 | <div class="variablelist"> | |
699 | <p class="title"><b></b></p> | |
700 | <dl> | |
701 | <dt><span class="term">Precondition:</span></dt> | |
702 | <dd><p> | |
703 | The calling fiber doesn't own the mutex. | |
704 | </p></dd> | |
705 | <dt><span class="term">Effects:</span></dt> | |
706 | <dd><p> | |
707 | Attempt to obtain ownership for the current fiber. Blocks until | |
708 | ownership can be obtained, or the specified time is reached. | |
709 | If the specified time has already passed, behaves as <a class="link" href="pooled_fixedsize.html#timed_mutex_try_lock"> <code class="computeroutput">timed_mutex::try_lock()</code></a>. | |
710 | </p></dd> | |
711 | <dt><span class="term">Returns:</span></dt> | |
712 | <dd><p> | |
713 | <code class="computeroutput"><span class="keyword">true</span></code> if ownership | |
714 | was obtained for the current fiber, <code class="computeroutput"><span class="keyword">false</span></code> | |
715 | otherwise. | |
716 | </p></dd> | |
717 | <dt><span class="term">Throws:</span></dt> | |
718 | <dd><p> | |
719 | <code class="computeroutput"><span class="identifier">lock_error</span></code>, timeout-related | |
720 | exceptions. | |
721 | </p></dd> | |
722 | <dt><span class="term">Error Conditions:</span></dt> | |
723 | <dd><p> | |
724 | <span class="bold"><strong>resource_deadlock_would_occur</strong></span>: | |
725 | if <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
726 | already owns the mutex. | |
727 | </p></dd> | |
728 | </dl> | |
729 | </div> | |
730 | <p> | |
731 | </p> | |
732 | <h5> | |
733 | <a name="timed_mutex_try_lock_for_bridgehead"></a> | |
734 | <span><a name="timed_mutex_try_lock_for"></a></span> | |
735 | <a class="link" href="pooled_fixedsize.html#timed_mutex_try_lock_for">Templated | |
736 | member function <code class="computeroutput">try_lock_for</code>()</a> | |
737 | </h5> | |
738 | <p> | |
739 | </p> | |
740 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
741 | <span class="keyword">bool</span> <span class="identifier">try_lock_for</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
742 | </pre> | |
743 | <div class="variablelist"> | |
744 | <p class="title"><b></b></p> | |
745 | <dl> | |
746 | <dt><span class="term">Precondition:</span></dt> | |
747 | <dd><p> | |
748 | The calling fiber doesn't own the mutex. | |
749 | </p></dd> | |
750 | <dt><span class="term">Effects:</span></dt> | |
751 | <dd><p> | |
752 | Attempt to obtain ownership for the current fiber. Blocks until | |
753 | ownership can be obtained, or the specified time is reached. | |
754 | If the specified time has already passed, behaves as <a class="link" href="pooled_fixedsize.html#timed_mutex_try_lock"> <code class="computeroutput">timed_mutex::try_lock()</code></a>. | |
755 | </p></dd> | |
756 | <dt><span class="term">Returns:</span></dt> | |
757 | <dd><p> | |
758 | <code class="computeroutput"><span class="keyword">true</span></code> if ownership | |
759 | was obtained for the current fiber, <code class="computeroutput"><span class="keyword">false</span></code> | |
760 | otherwise. | |
761 | </p></dd> | |
762 | <dt><span class="term">Throws:</span></dt> | |
763 | <dd><p> | |
764 | <code class="computeroutput"><span class="identifier">lock_error</span></code>, timeout-related | |
765 | exceptions. | |
766 | </p></dd> | |
767 | <dt><span class="term">Error Conditions:</span></dt> | |
768 | <dd><p> | |
769 | <span class="bold"><strong>resource_deadlock_would_occur</strong></span>: | |
770 | if <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
771 | already owns the mutex. | |
772 | </p></dd> | |
773 | </dl> | |
774 | </div> | |
775 | <p> | |
776 | </p> | |
777 | <h5> | |
778 | <a name="class_recursive_mutex_bridgehead"></a> | |
779 | <span><a name="class_recursive_mutex"></a></span> | |
780 | <a class="link" href="pooled_fixedsize.html#class_recursive_mutex">Class | |
781 | <code class="computeroutput">recursive_mutex</code></a> | |
782 | </h5> | |
783 | <p> | |
784 | </p> | |
785 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">recursive_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
786 | ||
787 | <span class="keyword">class</span> <span class="identifier">recursive_mutex</span> <span class="special">{</span> | |
788 | <span class="keyword">public</span><span class="special">:</span> | |
789 | <span class="identifier">recursive_mutex</span><span class="special">();</span> | |
790 | <span class="special">~</span><span class="identifier">recursive_mutex</span><span class="special">();</span> | |
791 | ||
792 | <span class="identifier">recursive_mutex</span><span class="special">(</span> <span class="identifier">recursive_mutex</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
793 | <span class="identifier">recursive_mutex</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">recursive_mutex</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
794 | ||
795 | <span class="keyword">void</span> <span class="identifier">lock</span><span class="special">();</span> | |
796 | <span class="keyword">bool</span> <span class="identifier">try_lock</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
797 | <span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">();</span> | |
798 | <span class="special">};</span> | |
799 | </pre> | |
800 | <p> | |
801 | <a class="link" href="pooled_fixedsize.html#class_recursive_mutex"> <code class="computeroutput">recursive_mutex</code></a> provides an exclusive-ownership | |
802 | recursive mutex. At most one fiber can own the lock on a given instance | |
803 | of <a class="link" href="pooled_fixedsize.html#class_recursive_mutex"> <code class="computeroutput">recursive_mutex</code></a> at any time. Multiple concurrent | |
804 | calls to <code class="computeroutput"><span class="identifier">lock</span><span class="special">()</span></code>, | |
805 | <code class="computeroutput"><span class="identifier">try_lock</span><span class="special">()</span></code> | |
806 | and <code class="computeroutput"><span class="identifier">unlock</span><span class="special">()</span></code> | |
807 | shall be permitted. A fiber that already has exclusive ownership of | |
808 | a given <a class="link" href="pooled_fixedsize.html#class_recursive_mutex"> <code class="computeroutput">recursive_mutex</code></a> instance can call <code class="computeroutput"><span class="identifier">lock</span><span class="special">()</span></code> | |
809 | or <code class="computeroutput"><span class="identifier">try_lock</span><span class="special">()</span></code> | |
810 | to acquire an additional level of ownership of the mutex. <code class="computeroutput"><span class="identifier">unlock</span><span class="special">()</span></code> | |
811 | must be called once for each level of ownership acquired by a single | |
812 | fiber before ownership can be acquired by another fiber. | |
813 | </p> | |
814 | <p> | |
815 | </p> | |
816 | <h5> | |
817 | <a name="recursive_mutex_lock_bridgehead"></a> | |
818 | <span><a name="recursive_mutex_lock"></a></span> | |
819 | <a class="link" href="pooled_fixedsize.html#recursive_mutex_lock">Member | |
820 | function <code class="computeroutput">lock</code>()</a> | |
821 | </h5> | |
822 | <p> | |
823 | </p> | |
824 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">lock</span><span class="special">();</span> | |
825 | </pre> | |
826 | <div class="variablelist"> | |
827 | <p class="title"><b></b></p> | |
828 | <dl> | |
829 | <dt><span class="term">Effects:</span></dt> | |
830 | <dd><p> | |
831 | The current fiber blocks until ownership can be obtained. | |
832 | </p></dd> | |
833 | <dt><span class="term">Throws:</span></dt> | |
834 | <dd><p> | |
835 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
836 | </p></dd> | |
837 | </dl> | |
838 | </div> | |
839 | <p> | |
840 | </p> | |
841 | <h5> | |
842 | <a name="recursive_mutex_try_lock_bridgehead"></a> | |
843 | <span><a name="recursive_mutex_try_lock"></a></span> | |
844 | <a class="link" href="pooled_fixedsize.html#recursive_mutex_try_lock">Member | |
845 | function <code class="computeroutput">try_lock</code>()</a> | |
846 | </h5> | |
847 | <p> | |
848 | </p> | |
849 | <pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">try_lock</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
850 | </pre> | |
851 | <div class="variablelist"> | |
852 | <p class="title"><b></b></p> | |
853 | <dl> | |
854 | <dt><span class="term">Effects:</span></dt> | |
855 | <dd><p> | |
856 | Attempt to obtain ownership for the current fiber without blocking. | |
857 | </p></dd> | |
858 | <dt><span class="term">Returns:</span></dt> | |
859 | <dd><p> | |
860 | <code class="computeroutput"><span class="keyword">true</span></code> if ownership | |
861 | was obtained for the current fiber, <code class="computeroutput"><span class="keyword">false</span></code> | |
862 | otherwise. | |
863 | </p></dd> | |
864 | <dt><span class="term">Throws:</span></dt> | |
865 | <dd><p> | |
866 | Nothing. | |
867 | </p></dd> | |
868 | </dl> | |
869 | </div> | |
870 | <p> | |
871 | </p> | |
872 | <h5> | |
873 | <a name="recursive_mutex_unlock_bridgehead"></a> | |
874 | <span><a name="recursive_mutex_unlock"></a></span> | |
875 | <a class="link" href="pooled_fixedsize.html#recursive_mutex_unlock">Member | |
876 | function <code class="computeroutput">unlock</code>()</a> | |
877 | </h5> | |
878 | <p> | |
879 | </p> | |
880 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">();</span> | |
881 | </pre> | |
882 | <div class="variablelist"> | |
883 | <p class="title"><b></b></p> | |
884 | <dl> | |
885 | <dt><span class="term">Effects:</span></dt> | |
886 | <dd><p> | |
887 | Releases a lock on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by the current fiber. | |
888 | </p></dd> | |
889 | <dt><span class="term">Throws:</span></dt> | |
890 | <dd><p> | |
891 | <code class="computeroutput"><span class="identifier">lock_error</span></code> | |
892 | </p></dd> | |
893 | <dt><span class="term">Error Conditions:</span></dt> | |
894 | <dd><p> | |
895 | <span class="bold"><strong>operation_not_permitted</strong></span>: if | |
896 | <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
897 | does not own the mutex. | |
898 | </p></dd> | |
899 | </dl> | |
900 | </div> | |
901 | <p> | |
902 | </p> | |
903 | <h5> | |
904 | <a name="class_recursive_timed_mutex_bridgehead"></a> | |
905 | <span><a name="class_recursive_timed_mutex"></a></span> | |
906 | <a class="link" href="pooled_fixedsize.html#class_recursive_timed_mutex">Class | |
907 | <code class="computeroutput">recursive_timed_mutex</code></a> | |
908 | </h5> | |
909 | <p> | |
910 | </p> | |
911 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">recursive_timed_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
912 | ||
913 | <span class="keyword">class</span> <span class="identifier">recursive_timed_mutex</span> <span class="special">{</span> | |
914 | <span class="keyword">public</span><span class="special">:</span> | |
915 | <span class="identifier">recursive_timed_mutex</span><span class="special">();</span> | |
916 | <span class="special">~</span><span class="identifier">recursive_timed_mutex</span><span class="special">();</span> | |
917 | ||
918 | <span class="identifier">recursive_timed_mutex</span><span class="special">(</span> <span class="identifier">recursive_timed_mutex</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
919 | <span class="identifier">recursive_timed_mutex</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">recursive_timed_mutex</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
920 | ||
921 | <span class="keyword">void</span> <span class="identifier">lock</span><span class="special">();</span> | |
922 | <span class="keyword">bool</span> <span class="identifier">try_lock</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
923 | <span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">();</span> | |
924 | ||
925 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
926 | <span class="keyword">bool</span> <span class="identifier">try_lock_until</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
927 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
928 | <span class="keyword">bool</span> <span class="identifier">try_lock_for</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
929 | <span class="special">};</span> | |
930 | </pre> | |
931 | <p> | |
932 | <a class="link" href="pooled_fixedsize.html#class_recursive_timed_mutex"> <code class="computeroutput">recursive_timed_mutex</code></a> provides an exclusive-ownership | |
933 | recursive mutex. At most one fiber can own the lock on a given instance | |
934 | of <a class="link" href="pooled_fixedsize.html#class_recursive_timed_mutex"> <code class="computeroutput">recursive_timed_mutex</code></a> at any time. Multiple | |
935 | concurrent calls to <code class="computeroutput"><span class="identifier">lock</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">try_lock</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">try_lock_for</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">try_lock_until</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">unlock</span><span class="special">()</span></code> shall be permitted. A fiber that | |
936 | already has exclusive ownership of a given <a class="link" href="pooled_fixedsize.html#class_recursive_timed_mutex"> <code class="computeroutput">recursive_timed_mutex</code></a> instance | |
937 | can call <code class="computeroutput"><span class="identifier">lock</span><span class="special">()</span></code>, | |
938 | <code class="computeroutput"><span class="identifier">try_lock</span><span class="special">()</span></code>, | |
939 | <code class="computeroutput"><span class="identifier">try_lock_for</span><span class="special">()</span></code> | |
940 | or <code class="computeroutput"><span class="identifier">try_lock_until</span><span class="special">()</span></code> | |
941 | to acquire an additional level of ownership of the mutex. <code class="computeroutput"><span class="identifier">unlock</span><span class="special">()</span></code> | |
942 | must be called once for each level of ownership acquired by a single | |
943 | fiber before ownership can be acquired by another fiber. | |
944 | </p> | |
945 | <p> | |
946 | </p> | |
947 | <h5> | |
948 | <a name="recursive_timed_mutex_lock_bridgehead"></a> | |
949 | <span><a name="recursive_timed_mutex_lock"></a></span> | |
950 | <a class="link" href="pooled_fixedsize.html#recursive_timed_mutex_lock">Member | |
951 | function <code class="computeroutput">lock</code>()</a> | |
952 | </h5> | |
953 | <p> | |
954 | </p> | |
955 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">lock</span><span class="special">();</span> | |
956 | </pre> | |
957 | <div class="variablelist"> | |
958 | <p class="title"><b></b></p> | |
959 | <dl> | |
960 | <dt><span class="term">Effects:</span></dt> | |
961 | <dd><p> | |
962 | The current fiber blocks until ownership can be obtained. | |
963 | </p></dd> | |
964 | <dt><span class="term">Throws:</span></dt> | |
965 | <dd><p> | |
966 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
967 | </p></dd> | |
968 | </dl> | |
969 | </div> | |
970 | <p> | |
971 | </p> | |
972 | <h5> | |
973 | <a name="recursive_timed_mutex_try_lock_bridgehead"></a> | |
974 | <span><a name="recursive_timed_mutex_try_lock"></a></span> | |
975 | <a class="link" href="pooled_fixedsize.html#recursive_timed_mutex_try_lock">Member | |
976 | function <code class="computeroutput">try_lock</code>()</a> | |
977 | </h5> | |
978 | <p> | |
979 | </p> | |
980 | <pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">try_lock</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
981 | </pre> | |
982 | <div class="variablelist"> | |
983 | <p class="title"><b></b></p> | |
984 | <dl> | |
985 | <dt><span class="term">Effects:</span></dt> | |
986 | <dd><p> | |
987 | Attempt to obtain ownership for the current fiber without blocking. | |
988 | </p></dd> | |
989 | <dt><span class="term">Returns:</span></dt> | |
990 | <dd><p> | |
991 | <code class="computeroutput"><span class="keyword">true</span></code> if ownership | |
992 | was obtained for the current fiber, <code class="computeroutput"><span class="keyword">false</span></code> | |
993 | otherwise. | |
994 | </p></dd> | |
995 | <dt><span class="term">Throws:</span></dt> | |
996 | <dd><p> | |
997 | Nothing. | |
998 | </p></dd> | |
999 | </dl> | |
1000 | </div> | |
1001 | <p> | |
1002 | </p> | |
1003 | <h5> | |
1004 | <a name="recursive_timed_mutex_unlock_bridgehead"></a> | |
1005 | <span><a name="recursive_timed_mutex_unlock"></a></span> | |
1006 | <a class="link" href="pooled_fixedsize.html#recursive_timed_mutex_unlock">Member | |
1007 | function <code class="computeroutput">unlock</code>()</a> | |
1008 | </h5> | |
1009 | <p> | |
1010 | </p> | |
1011 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">unlock</span><span class="special">();</span> | |
1012 | </pre> | |
1013 | <div class="variablelist"> | |
1014 | <p class="title"><b></b></p> | |
1015 | <dl> | |
1016 | <dt><span class="term">Effects:</span></dt> | |
1017 | <dd><p> | |
1018 | Releases a lock on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> by the current fiber. | |
1019 | </p></dd> | |
1020 | <dt><span class="term">Throws:</span></dt> | |
1021 | <dd><p> | |
1022 | <code class="computeroutput"><span class="identifier">lock_error</span></code> | |
1023 | </p></dd> | |
1024 | <dt><span class="term">Error Conditions:</span></dt> | |
1025 | <dd><p> | |
1026 | <span class="bold"><strong>operation_not_permitted</strong></span>: if | |
1027 | <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span></code> | |
1028 | does not own the mutex. | |
1029 | </p></dd> | |
1030 | </dl> | |
1031 | </div> | |
1032 | <p> | |
1033 | </p> | |
1034 | <h5> | |
1035 | <a name="recursive_timed_mutex_try_lock_until_bridgehead"></a> | |
1036 | <span><a name="recursive_timed_mutex_try_lock_until"></a></span> | |
1037 | <a class="link" href="pooled_fixedsize.html#recursive_timed_mutex_try_lock_until">Templated | |
1038 | member function <code class="computeroutput">try_lock_until</code>()</a> | |
1039 | </h5> | |
1040 | <p> | |
1041 | </p> | |
1042 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
1043 | <span class="keyword">bool</span> <span class="identifier">try_lock_until</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
1044 | </pre> | |
1045 | <div class="variablelist"> | |
1046 | <p class="title"><b></b></p> | |
1047 | <dl> | |
1048 | <dt><span class="term">Effects:</span></dt> | |
1049 | <dd><p> | |
1050 | Attempt to obtain ownership for the current fiber. Blocks until | |
1051 | ownership can be obtained, or the specified time is reached. | |
1052 | If the specified time has already passed, behaves as <a class="link" href="pooled_fixedsize.html#recursive_timed_mutex_try_lock"> <code class="computeroutput">recursive_timed_mutex::try_lock()</code></a>. | |
1053 | </p></dd> | |
1054 | <dt><span class="term">Returns:</span></dt> | |
1055 | <dd><p> | |
1056 | <code class="computeroutput"><span class="keyword">true</span></code> if ownership | |
1057 | was obtained for the current fiber, <code class="computeroutput"><span class="keyword">false</span></code> | |
1058 | otherwise. | |
1059 | </p></dd> | |
1060 | <dt><span class="term">Throws:</span></dt> | |
1061 | <dd><p> | |
1062 | Timeout-related exceptions. | |
1063 | </p></dd> | |
1064 | </dl> | |
1065 | </div> | |
1066 | <p> | |
1067 | </p> | |
1068 | <h5> | |
1069 | <a name="recursive_timed_mutex_try_lock_for_bridgehead"></a> | |
1070 | <span><a name="recursive_timed_mutex_try_lock_for"></a></span> | |
1071 | <a class="link" href="pooled_fixedsize.html#recursive_timed_mutex_try_lock_for">Templated | |
1072 | member function <code class="computeroutput">try_lock_for</code>()</a> | |
1073 | </h5> | |
1074 | <p> | |
1075 | </p> | |
1076 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
1077 | <span class="keyword">bool</span> <span class="identifier">try_lock_for</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
1078 | </pre> | |
1079 | <div class="variablelist"> | |
1080 | <p class="title"><b></b></p> | |
1081 | <dl> | |
1082 | <dt><span class="term">Effects:</span></dt> | |
1083 | <dd><p> | |
1084 | Attempt to obtain ownership for the current fiber. Blocks until | |
1085 | ownership can be obtained, or the specified time is reached. | |
1086 | If the specified time has already passed, behaves as <a class="link" href="pooled_fixedsize.html#recursive_timed_mutex_try_lock"> <code class="computeroutput">recursive_timed_mutex::try_lock()</code></a>. | |
1087 | </p></dd> | |
1088 | <dt><span class="term">Returns:</span></dt> | |
1089 | <dd><p> | |
1090 | <code class="computeroutput"><span class="keyword">true</span></code> if ownership | |
1091 | was obtained for the current fiber, <code class="computeroutput"><span class="keyword">false</span></code> | |
1092 | otherwise. | |
1093 | </p></dd> | |
1094 | <dt><span class="term">Throws:</span></dt> | |
1095 | <dd><p> | |
1096 | Timeout-related exceptions. | |
1097 | </p></dd> | |
1098 | </dl> | |
1099 | </div> | |
1100 | </div> | |
1101 | <div class="section"> | |
1102 | <div class="titlepage"><div><div><h6 class="title"> | |
1103 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions" title="Condition Variables">Condition | |
1104 | Variables</a> | |
1105 | </h6></div></div></div> | |
1106 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.h0"></a> | |
1107 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.synopsis"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.synopsis">Synopsis</a> | |
1108 | </h7><pre class="programlisting"><span class="keyword">enum</span> <span class="keyword">class</span> <span class="identifier">cv_status</span><span class="special">;</span> <span class="special">{</span> | |
1109 | <span class="identifier">no_timeout</span><span class="special">,</span> | |
1110 | <span class="identifier">timeout</span> | |
1111 | <span class="special">};</span> | |
1112 | ||
1113 | <span class="keyword">class</span> <span class="identifier">condition_variable</span><span class="special">;</span> | |
1114 | <span class="keyword">class</span> <span class="identifier">condition_variable_any</span><span class="special">;</span> | |
1115 | </pre> | |
1116 | <p> | |
1117 | The class <a class="link" href="pooled_fixedsize.html#class_condition_variable"> <code class="computeroutput">condition_variable</code></a> provides a mechanism | |
1118 | for a fiber to wait for notification from another fiber. When the fiber | |
1119 | awakens from the wait, then it checks to see if the appropriate condition | |
1120 | is now true, and continues if so. If the condition is not true, then | |
1121 | the fiber calls <code class="computeroutput"><span class="identifier">wait</span></code> | |
1122 | again to resume waiting. In the simplest case, this condition is just | |
1123 | a boolean variable: | |
1124 | </p> | |
1125 | <pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">condition_variable</span> <span class="identifier">cond</span><span class="special">;</span> | |
1126 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span> <span class="identifier">mtx</span><span class="special">;</span> | |
1127 | <span class="keyword">bool</span> <span class="identifier">data_ready</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span> | |
1128 | ||
1129 | <span class="keyword">void</span> <span class="identifier">process_data</span><span class="special">();</span> | |
1130 | ||
1131 | <span class="keyword">void</span> <span class="identifier">wait_for_data_to_process</span><span class="special">()</span> <span class="special">{</span> | |
1132 | <span class="special">{</span> | |
1133 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">></span> <span class="identifier">lk</span><span class="special">(</span> <span class="identifier">mtx</span><span class="special">);</span> | |
1134 | <span class="keyword">while</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">data_ready</span><span class="special">)</span> <span class="special">{</span> | |
1135 | <span class="identifier">cond</span><span class="special">.</span><span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">);</span> | |
1136 | <span class="special">}</span> | |
1137 | <span class="special">}</span> <span class="comment">// release lk</span> | |
1138 | <span class="identifier">process_data</span><span class="special">();</span> | |
1139 | <span class="special">}</span> | |
1140 | </pre> | |
1141 | <p> | |
1142 | Notice that the <code class="computeroutput"><span class="identifier">lk</span></code> | |
1143 | is passed to <a class="link" href="pooled_fixedsize.html#condition_variable_wait"> <code class="computeroutput">condition_variable::wait()</code></a>: <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> | |
1144 | will atomically add the fiber to the set of fibers waiting on the condition | |
1145 | variable, and unlock the <a class="link" href="pooled_fixedsize.html#class_mutex"> <code class="computeroutput">mutex</code></a>. When the fiber is awakened, | |
1146 | the <code class="computeroutput"><span class="identifier">mutex</span></code> will be locked | |
1147 | again before the call to <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> returns. This allows other fibers | |
1148 | to acquire the <code class="computeroutput"><span class="identifier">mutex</span></code> | |
1149 | in order to update the shared data, and ensures that the data associated | |
1150 | with the condition is correctly synchronized. | |
1151 | </p> | |
1152 | <p> | |
1153 | <code class="computeroutput"><span class="identifier">wait_for_data_to_process</span><span class="special">()</span></code> could equivalently be written: | |
1154 | </p> | |
1155 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">wait_for_data_to_process</span><span class="special">()</span> <span class="special">{</span> | |
1156 | <span class="special">{</span> | |
1157 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">></span> <span class="identifier">lk</span><span class="special">(</span> <span class="identifier">mtx</span><span class="special">);</span> | |
1158 | <span class="comment">// make condition_variable::wait() perform the loop</span> | |
1159 | <span class="identifier">cond</span><span class="special">.</span><span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">,</span> <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">data_ready</span><span class="special">;</span> <span class="special">});</span> | |
1160 | <span class="special">}</span> <span class="comment">// release lk</span> | |
1161 | <span class="identifier">process_data</span><span class="special">();</span> | |
1162 | <span class="special">}</span> | |
1163 | </pre> | |
1164 | <p> | |
1165 | In the meantime, another fiber sets <code class="computeroutput"><span class="identifier">data_ready</span></code> | |
1166 | to <code class="computeroutput"><span class="keyword">true</span></code>, and then calls | |
1167 | either <a class="link" href="pooled_fixedsize.html#condition_variable_notify_one"> <code class="computeroutput">condition_variable::notify_one()</code></a> or | |
1168 | <a class="link" href="pooled_fixedsize.html#condition_variable_notify_all"> <code class="computeroutput">condition_variable::notify_all()</code></a> on the | |
1169 | <a class="link" href="pooled_fixedsize.html#class_condition_variable"> <code class="computeroutput">condition_variable</code></a> <code class="computeroutput"><span class="identifier">cond</span></code> | |
1170 | to wake one waiting fiber or all the waiting fibers respectively. | |
1171 | </p> | |
1172 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">retrieve_data</span><span class="special">();</span> | |
1173 | <span class="keyword">void</span> <span class="identifier">prepare_data</span><span class="special">();</span> | |
1174 | ||
1175 | <span class="keyword">void</span> <span class="identifier">prepare_data_for_processing</span><span class="special">()</span> <span class="special">{</span> | |
1176 | <span class="identifier">retrieve_data</span><span class="special">();</span> | |
1177 | <span class="identifier">prepare_data</span><span class="special">();</span> | |
1178 | <span class="special">{</span> | |
1179 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">></span> <span class="identifier">lk</span><span class="special">(</span> <span class="identifier">mtx</span><span class="special">);</span> | |
1180 | <span class="identifier">data_ready</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span> | |
1181 | <span class="special">}</span> | |
1182 | <span class="identifier">cond</span><span class="special">.</span><span class="identifier">notify_one</span><span class="special">();</span> | |
1183 | <span class="special">}</span> | |
1184 | </pre> | |
1185 | <p> | |
1186 | Note that the same <a class="link" href="pooled_fixedsize.html#class_mutex"> <code class="computeroutput">mutex</code></a> is locked before the shared data | |
1187 | is updated, but that the <code class="computeroutput"><span class="identifier">mutex</span></code> | |
1188 | does not have to be locked across the call to <a class="link" href="pooled_fixedsize.html#condition_variable_notify_one"> <code class="computeroutput">condition_variable::notify_one()</code></a>. | |
1189 | </p> | |
1190 | <p> | |
1191 | Locking is important because the synchronization objects provided by | |
1192 | <span class="bold"><strong>Boost.Fiber</strong></span> can be used to synchronize | |
1193 | fibers running on different threads. | |
1194 | </p> | |
1195 | <p> | |
1196 | <span class="bold"><strong>Boost.Fiber</strong></span> provides both <a class="link" href="pooled_fixedsize.html#class_condition_variable"> <code class="computeroutput">condition_variable</code></a> and | |
1197 | <a class="link" href="pooled_fixedsize.html#class_condition_variable_any"> <code class="computeroutput">condition_variable_any</code></a>. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">condition_variable</span></code> | |
1198 | can only wait on <a href="http://en.cppreference.com/w/cpp/thread/unique_lock" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span></code></a><code class="computeroutput"><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span></code> <a class="link" href="pooled_fixedsize.html#class_mutex"> <code class="computeroutput">mutex</code></a><code class="computeroutput"> <span class="special">></span></code> | |
1199 | while <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">condition_variable_any</span></code> can wait on | |
1200 | user-defined lock types. | |
1201 | </p> | |
1202 | <a name="condition_variable_spurious_wakeups"></a><h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.h1"></a> | |
1203 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.no_spurious_wakeups"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.no_spurious_wakeups">No | |
1204 | Spurious Wakeups</a> | |
1205 | </h7><p> | |
1206 | Neither <a class="link" href="pooled_fixedsize.html#class_condition_variable"> <code class="computeroutput">condition_variable</code></a> nor <a class="link" href="pooled_fixedsize.html#class_condition_variable_any"> <code class="computeroutput">condition_variable_any</code></a> are | |
1207 | subject to spurious wakeup: <a class="link" href="pooled_fixedsize.html#condition_variable_wait"> <code class="computeroutput">condition_variable::wait()</code></a> can | |
1208 | only wake up when <a class="link" href="pooled_fixedsize.html#condition_variable_notify_one"> <code class="computeroutput">condition_variable::notify_one()</code></a> or | |
1209 | <a class="link" href="pooled_fixedsize.html#condition_variable_notify_all"> <code class="computeroutput">condition_variable::notify_all()</code></a> is called. | |
1210 | Even so, it is prudent to use one of the <code class="computeroutput"><span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lock</span><span class="special">,</span> <span class="identifier">predicate</span> | |
1211 | <span class="special">)</span></code> overloads. | |
1212 | </p> | |
1213 | <p> | |
1214 | Consider a set of consumer fibers processing items from a <a href="http://en.cppreference.com/w/cpp/container/queue" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">queue</span></code></a>. The queue is continually | |
1215 | populated by a set of producer fibers. | |
1216 | </p> | |
1217 | <p> | |
1218 | The consumer fibers might reasonably wait on a <code class="computeroutput"><span class="identifier">condition_variable</span></code> | |
1219 | as long as the queue remains <a href="http://en.cppreference.com/w/cpp/container/queue/empty" target="_top"><code class="computeroutput"><span class="identifier">empty</span><span class="special">()</span></code></a>. | |
1220 | </p> | |
1221 | <p> | |
1222 | Because producer fibers might <a href="http://en.cppreference.com/w/cpp/container/queue/push" target="_top"><code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code></a> | |
1223 | items to the queue in bursts, they call <a class="link" href="pooled_fixedsize.html#condition_variable_notify_all"> <code class="computeroutput">condition_variable::notify_all()</code></a> rather | |
1224 | than <a class="link" href="pooled_fixedsize.html#condition_variable_notify_one"> <code class="computeroutput">condition_variable::notify_one()</code></a>. | |
1225 | </p> | |
1226 | <p> | |
1227 | But a given consumer fiber might well wake up from <a class="link" href="pooled_fixedsize.html#condition_variable_wait"> <code class="computeroutput">condition_variable::wait()</code></a> and | |
1228 | find the queue <code class="computeroutput"><span class="identifier">empty</span><span class="special">()</span></code>, because other consumer fibers might | |
1229 | already have processed all pending items. | |
1230 | </p> | |
1231 | <p> | |
1232 | (See also <a class="link" href="pooled_fixedsize.html#spurious_wakeup">spurious wakeup</a>.) | |
1233 | </p> | |
1234 | <a name="class_cv_status"></a><h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.h2"></a> | |
1235 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.enumeration__code__phrase_role__identifier__cv_status__phrase___code_">Enumeration | |
1236 | <code class="computeroutput"><span class="identifier">cv_status</span></code></a> | |
1237 | </h7><p> | |
1238 | A timed wait operation might return because of timeout or not. | |
1239 | </p> | |
1240 | <pre class="programlisting"><span class="keyword">enum</span> <span class="keyword">class</span> <span class="identifier">cv_status</span> <span class="special">{</span> | |
1241 | <span class="identifier">no_timeout</span><span class="special">,</span> | |
1242 | <span class="identifier">timeout</span> | |
1243 | <span class="special">};</span> | |
1244 | </pre> | |
1245 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.h3"></a> | |
1246 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions._code__phrase_role__identifier__no_timeout__phrase___code_"><code class="computeroutput"><span class="identifier">no_timeout</span></code></a> | |
1247 | </h7><div class="variablelist"> | |
1248 | <p class="title"><b></b></p> | |
1249 | <dl> | |
1250 | <dt><span class="term">Effects:</span></dt> | |
1251 | <dd><p> | |
1252 | The condition variable was awakened with <code class="computeroutput"><span class="identifier">notify_one</span></code> | |
1253 | or <code class="computeroutput"><span class="identifier">notify_all</span></code>. | |
1254 | </p></dd> | |
1255 | </dl> | |
1256 | </div> | |
1257 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.h4"></a> | |
1258 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions._code__phrase_role__identifier__timeout__phrase___code_"><code class="computeroutput"><span class="identifier">timeout</span></code></a> | |
1259 | </h7><div class="variablelist"> | |
1260 | <p class="title"><b></b></p> | |
1261 | <dl> | |
1262 | <dt><span class="term">Effects:</span></dt> | |
1263 | <dd><p> | |
1264 | The condition variable was awakened by timeout. | |
1265 | </p></dd> | |
1266 | </dl> | |
1267 | </div> | |
1268 | <p> | |
1269 | </p> | |
1270 | <h5> | |
1271 | <a name="class_condition_variable_any_bridgehead"></a> | |
1272 | <span><a name="class_condition_variable_any"></a></span> | |
1273 | <a class="link" href="pooled_fixedsize.html#class_condition_variable_any">Class | |
1274 | <code class="computeroutput">condition_variable_any</code></a> | |
1275 | </h5> | |
1276 | <p> | |
1277 | </p> | |
1278 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">condition_variable</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
1279 | ||
1280 | <span class="keyword">class</span> condition_variable_any <span class="special">{</span> | |
1281 | <span class="keyword">public</span><span class="special">:</span> | |
1282 | condition_variable_any<span class="special">();</span> | |
1283 | <span class="special">~</span>condition_variable_any<span class="special">();</span> | |
1284 | ||
1285 | condition_variable_any<span class="special">(</span> condition_variable_any <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
1286 | condition_variable_any <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> condition_variable_any <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
1287 | ||
1288 | <span class="keyword">void</span> <span class="identifier">notify_one</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
1289 | <span class="keyword">void</span> <span class="identifier">notify_all</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
1290 | ||
1291 | template< typename LockType > | |
1292 | void <span class="identifier">wait</span><span class="special">(</span> LockType <span class="special">&);</span> | |
1293 | ||
1294 | <span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Pred</span> <span class="special">></span> | |
1295 | <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">(</span> LockType <span class="special">&,</span> <span class="identifier">Pred</span><span class="special">);</span> | |
1296 | ||
1297 | <span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
1298 | <span class="identifier">cv_status</span> <span class="identifier">wait_until</span><span class="special">(</span> LockType <span class="special">&,</span> | |
1299 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&);</span> | |
1300 | ||
1301 | <span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Pred</span> <span class="special">></span> | |
1302 | <span class="keyword">bool</span> <span class="identifier">wait_until</span><span class="special">(</span> LockType <span class="special">&,</span> | |
1303 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&,</span> | |
1304 | <span class="identifier">Pred</span><span class="special">);</span> | |
1305 | ||
1306 | <span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
1307 | <span class="identifier">cv_status</span> <span class="identifier">wait_for</span><span class="special">(</span> LockType <span class="special">&,</span> | |
1308 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&);</span> | |
1309 | ||
1310 | <span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Pred</span> <span class="special">></span> | |
1311 | <span class="keyword">bool</span> <span class="identifier">wait_for</span><span class="special">(</span> LockType <span class="special">&,</span> | |
1312 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&,</span> | |
1313 | <span class="identifier">Pred</span><span class="special">);</span> | |
1314 | <span class="special">};</span> | |
1315 | </pre> | |
1316 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.h5"></a> | |
1317 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.constructor">Constructor</a> | |
1318 | </h7><pre class="programlisting">condition_variable_any<span class="special">()</span> | |
1319 | </pre> | |
1320 | <div class="variablelist"> | |
1321 | <p class="title"><b></b></p> | |
1322 | <dl> | |
1323 | <dt><span class="term">Effects:</span></dt> | |
1324 | <dd><p> | |
1325 | Creates the object. | |
1326 | </p></dd> | |
1327 | <dt><span class="term">Throws:</span></dt> | |
1328 | <dd><p> | |
1329 | Nothing. | |
1330 | </p></dd> | |
1331 | </dl> | |
1332 | </div> | |
1333 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.h6"></a> | |
1334 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.destructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.destructor">Destructor</a> | |
1335 | </h7><pre class="programlisting"><span class="special">~</span>condition_variable_any<span class="special">()</span> | |
1336 | </pre> | |
1337 | <div class="variablelist"> | |
1338 | <p class="title"><b></b></p> | |
1339 | <dl> | |
1340 | <dt><span class="term">Precondition:</span></dt> | |
1341 | <dd><p> | |
1342 | All fibers waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> have been notified by a call | |
1343 | to <code class="computeroutput"><span class="identifier">notify_one</span></code> | |
1344 | or <code class="computeroutput"><span class="identifier">notify_all</span></code> | |
1345 | (though the respective calls to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
1346 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
1347 | <code class="computeroutput"><span class="identifier">wait_until</span></code> need | |
1348 | not have returned). | |
1349 | </p></dd> | |
1350 | <dt><span class="term">Effects:</span></dt> | |
1351 | <dd><p> | |
1352 | Destroys the object. | |
1353 | </p></dd> | |
1354 | </dl> | |
1355 | </div> | |
1356 | <p> | |
1357 | </p> | |
1358 | <h5> | |
1359 | <a name="condition_variable_any_notify_one_bridgehead"></a> | |
1360 | <span><a name="condition_variable_any_notify_one"></a></span> | |
1361 | <a class="link" href="pooled_fixedsize.html#condition_variable_any_notify_one">Member | |
1362 | function <code class="computeroutput">notify_one</code>()</a> | |
1363 | </h5> | |
1364 | <p> | |
1365 | </p> | |
1366 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">notify_one</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
1367 | </pre> | |
1368 | <div class="variablelist"> | |
1369 | <p class="title"><b></b></p> | |
1370 | <dl> | |
1371 | <dt><span class="term">Effects:</span></dt> | |
1372 | <dd><p> | |
1373 | If any fibers are currently <a class="link" href="../../overview.html#blocking"><span class="emphasis"><em>blocked</em></span></a> | |
1374 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
1375 | in a call to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
1376 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
1377 | <code class="computeroutput"><span class="identifier">wait_until</span></code>, unblocks | |
1378 | one of those fibers. | |
1379 | </p></dd> | |
1380 | <dt><span class="term">Throws:</span></dt> | |
1381 | <dd><p> | |
1382 | Nothing. | |
1383 | </p></dd> | |
1384 | <dt><span class="term">Note:</span></dt> | |
1385 | <dd><p> | |
1386 | It is arbitrary which waiting fiber is resumed. | |
1387 | </p></dd> | |
1388 | </dl> | |
1389 | </div> | |
1390 | <p> | |
1391 | </p> | |
1392 | <h5> | |
1393 | <a name="condition_variable_any_notify_all_bridgehead"></a> | |
1394 | <span><a name="condition_variable_any_notify_all"></a></span> | |
1395 | <a class="link" href="pooled_fixedsize.html#condition_variable_any_notify_all">Member | |
1396 | function <code class="computeroutput">notify_all</code>()</a> | |
1397 | </h5> | |
1398 | <p> | |
1399 | </p> | |
1400 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">notify_all</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
1401 | </pre> | |
1402 | <div class="variablelist"> | |
1403 | <p class="title"><b></b></p> | |
1404 | <dl> | |
1405 | <dt><span class="term">Effects:</span></dt> | |
1406 | <dd><p> | |
1407 | If any fibers are currently <a class="link" href="../../overview.html#blocking"><span class="emphasis"><em>blocked</em></span></a> | |
1408 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
1409 | in a call to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
1410 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
1411 | <code class="computeroutput"><span class="identifier">wait_until</span></code>, unblocks | |
1412 | all of those fibers. | |
1413 | </p></dd> | |
1414 | <dt><span class="term">Throws:</span></dt> | |
1415 | <dd><p> | |
1416 | Nothing. | |
1417 | </p></dd> | |
1418 | <dt><span class="term">Note:</span></dt> | |
1419 | <dd><p> | |
1420 | This is why a waiting fiber must <span class="emphasis"><em>also</em></span> check | |
1421 | for the desired program state using a mechanism external to the | |
1422 | <code class="computeroutput">condition_variable_any</code>, and retry the wait until that state is | |
1423 | reached. A fiber waiting on a <code class="computeroutput">condition_variable_any</code> might well | |
1424 | wake up a number of times before the desired state is reached. | |
1425 | </p></dd> | |
1426 | </dl> | |
1427 | </div> | |
1428 | <p> | |
1429 | </p> | |
1430 | <h5> | |
1431 | <a name="condition_variable_any_wait_bridgehead"></a> | |
1432 | <span><a name="condition_variable_any_wait"></a></span> | |
1433 | <a class="link" href="pooled_fixedsize.html#condition_variable_any_wait">Templated | |
1434 | member function <code class="computeroutput">wait</code>()</a> | |
1435 | </h5> | |
1436 | <p> | |
1437 | </p> | |
1438 | <pre class="programlisting">template< typename LockType > | |
1439 | void <span class="identifier">wait</span><span class="special">(</span> LockType <span class="special">&</span> <span class="identifier">lk</span><span class="special">);</span> | |
1440 | ||
1441 | <span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Pred</span> <span class="special">></span> | |
1442 | <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">(</span> LockType <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> <span class="identifier">Pred</span> <span class="identifier">pred</span><span class="special">);</span> | |
1443 | </pre> | |
1444 | <div class="variablelist"> | |
1445 | <p class="title"><b></b></p> | |
1446 | <dl> | |
1447 | <dt><span class="term">Precondition:</span></dt> | |
1448 | <dd><p> | |
1449 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
1450 | by the current fiber, and either no other fiber is currently | |
1451 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>, | |
1452 | or the execution of the <a href="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex" target="_top"><code class="computeroutput"><span class="identifier">mutex</span><span class="special">()</span></code></a> | |
1453 | member function on the <code class="computeroutput"><span class="identifier">lk</span></code> | |
1454 | objects supplied in the calls to <code class="computeroutput"><span class="identifier">wait</span></code> | |
1455 | in all the fibers currently waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> would return the same value | |
1456 | as <code class="computeroutput"><span class="identifier">lk</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">()</span></code> | |
1457 | for this call to <code class="computeroutput"><span class="identifier">wait</span></code>. | |
1458 | </p></dd> | |
1459 | <dt><span class="term">Effects:</span></dt> | |
1460 | <dd> | |
1461 | <p> | |
1462 | Atomically call <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">()</span></code> and blocks the current fiber. | |
1463 | The fiber will unblock when notified by a call to <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_one</span><span class="special">()</span></code> | |
1464 | or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_all</span><span class="special">()</span></code>. | |
1465 | When the fiber is unblocked (for whatever reason), the lock is | |
1466 | reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> before the call to <code class="computeroutput"><span class="identifier">wait</span></code> returns. The lock is also | |
1467 | reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> if the function exits with | |
1468 | an exception. The member function accepting <code class="computeroutput"><span class="identifier">pred</span></code> | |
1469 | is shorthand for: | |
1470 | </p> | |
1471 | <pre class="programlisting"><span class="keyword">while</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">pred</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> | |
1472 | <span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">);</span> | |
1473 | <span class="special">}</span> | |
1474 | </pre> | |
1475 | <p> | |
1476 | </p> | |
1477 | </dd> | |
1478 | <dt><span class="term">Postcondition:</span></dt> | |
1479 | <dd><p> | |
1480 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
1481 | by the current fiber. | |
1482 | </p></dd> | |
1483 | <dt><span class="term">Throws:</span></dt> | |
1484 | <dd><p> | |
1485 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> if | |
1486 | an error occurs, <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
1487 | if the wait was interrupted by a call to <a class="link" href="../../fiber_mgmt/fiber.html#fiber_interrupt"> <code class="computeroutput">fiber::interrupt()</code></a> on | |
1488 | the <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> object associated with the current fiber | |
1489 | of execution. | |
1490 | </p></dd> | |
1491 | <dt><span class="term">Note:</span></dt> | |
1492 | <dd><p> | |
1493 | The Precondition is a bit dense. It merely states that all the | |
1494 | fibers concurrently calling <code class="computeroutput"><span class="identifier">wait</span></code> | |
1495 | on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
1496 | must wait on <code class="computeroutput"><span class="identifier">lk</span></code> | |
1497 | objects governing the <span class="emphasis"><em>same</em></span> <a class="link" href="pooled_fixedsize.html#class_mutex"> <code class="computeroutput">mutex</code></a>. | |
1498 | Three distinct objects are involved in any <code class="computeroutput">condition_variable_any::wait()</code> call: | |
1499 | the <code class="computeroutput">condition_variable_any</code> itself, the <code class="computeroutput"><span class="identifier">mutex</span></code> | |
1500 | coordinating access between fibers and a local lock object (e.g. | |
1501 | <a href="http://en.cppreference.com/w/cpp/thread/unique_lock" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span></code></a>). In general, | |
1502 | you can partition the lifespan of a given <code class="computeroutput">condition_variable_any</code> instance | |
1503 | into periods with one or more fibers waiting on it, separated | |
1504 | by periods when no fibers are waiting on it. When more than one | |
1505 | fiber is waiting on that <code class="computeroutput">condition_variable_any</code>, all must pass | |
1506 | lock objects referencing the <span class="emphasis"><em>same</em></span> <code class="computeroutput"><span class="identifier">mutex</span></code> instance. | |
1507 | </p></dd> | |
1508 | </dl> | |
1509 | </div> | |
1510 | <p> | |
1511 | </p> | |
1512 | <h5> | |
1513 | <a name="condition_variable_any_wait_until_bridgehead"></a> | |
1514 | <span><a name="condition_variable_any_wait_until"></a></span> | |
1515 | <a class="link" href="pooled_fixedsize.html#condition_variable_any_wait_until">Templated | |
1516 | member function <code class="computeroutput">wait_until</code>()</a> | |
1517 | </h5> | |
1518 | <p> | |
1519 | </p> | |
1520 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
1521 | <span class="identifier">cv_status</span> <span class="identifier">wait_until</span><span class="special">(</span> LockType <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> | |
1522 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">abs_time</span><span class="special">);</span> | |
1523 | ||
1524 | <span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Pred</span> <span class="special">></span> | |
1525 | <span class="keyword">bool</span> <span class="identifier">wait_until</span><span class="special">(</span> LockType <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> | |
1526 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">abs_time</span><span class="special">,</span> | |
1527 | <span class="identifier">Pred</span> <span class="identifier">pred</span><span class="special">);</span> | |
1528 | </pre> | |
1529 | <div class="variablelist"> | |
1530 | <p class="title"><b></b></p> | |
1531 | <dl> | |
1532 | <dt><span class="term">Precondition:</span></dt> | |
1533 | <dd><p> | |
1534 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
1535 | by the current fiber, and either no other fiber is currently | |
1536 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>, | |
1537 | or the execution of the <code class="computeroutput"><span class="identifier">mutex</span><span class="special">()</span></code> member function on the <code class="computeroutput"><span class="identifier">lk</span></code> objects supplied in the | |
1538 | calls to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
1539 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
1540 | <code class="computeroutput"><span class="identifier">wait_until</span></code> in | |
1541 | all the fibers currently waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> would return the same value | |
1542 | as <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">mutex</span><span class="special">()</span></code> | |
1543 | for this call to <code class="computeroutput"><span class="identifier">wait_until</span></code>. | |
1544 | </p></dd> | |
1545 | <dt><span class="term">Effects:</span></dt> | |
1546 | <dd> | |
1547 | <p> | |
1548 | Atomically call <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">()</span></code> and blocks the current fiber. | |
1549 | The fiber will unblock when notified by a call to <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_one</span><span class="special">()</span></code> | |
1550 | or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_all</span><span class="special">()</span></code>, | |
1551 | when the system time would be equal to or later than the specified | |
1552 | <code class="computeroutput"><span class="identifier">abs_time</span></code>. When | |
1553 | the fiber is unblocked (for whatever reason), the lock is reacquired | |
1554 | by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> before the call to <code class="computeroutput"><span class="identifier">wait_until</span></code> returns. The lock | |
1555 | is also reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> if the function exits with | |
1556 | an exception. The member function accepting <code class="computeroutput"><span class="identifier">pred</span></code> | |
1557 | is shorthand for: | |
1558 | </p> | |
1559 | <pre class="programlisting"><span class="keyword">while</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">pred</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> | |
1560 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">timeout</span> <span class="special">==</span> <span class="identifier">wait_until</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">,</span> <span class="identifier">abs_time</span><span class="special">)</span> <span class="special">)</span> | |
1561 | <span class="keyword">return</span> <span class="identifier">pred</span><span class="special">();</span> | |
1562 | <span class="special">}</span> | |
1563 | <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span> | |
1564 | </pre> | |
1565 | <p> | |
1566 | That is, even if <code class="computeroutput"><span class="identifier">wait_until</span><span class="special">()</span></code> times out, it can still return | |
1567 | <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="identifier">pred</span><span class="special">()</span></code> | |
1568 | returns <code class="computeroutput"><span class="keyword">true</span></code> at | |
1569 | that time. | |
1570 | </p> | |
1571 | </dd> | |
1572 | <dt><span class="term">Postcondition:</span></dt> | |
1573 | <dd><p> | |
1574 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
1575 | by the current fiber. | |
1576 | </p></dd> | |
1577 | <dt><span class="term">Throws:</span></dt> | |
1578 | <dd><p> | |
1579 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> if | |
1580 | an error occurs, <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
1581 | if the wait was interrupted by a call to <a class="link" href="../../fiber_mgmt/fiber.html#fiber_interrupt"> <code class="computeroutput">fiber::interrupt()</code></a> on | |
1582 | the <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> object associated with the current fiber | |
1583 | of execution or timeout-related exceptions. | |
1584 | </p></dd> | |
1585 | <dt><span class="term">Returns:</span></dt> | |
1586 | <dd><p> | |
1587 | The overload without <code class="computeroutput"><span class="identifier">pred</span></code> | |
1588 | returns <code class="computeroutput"><span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">no_timeout</span></code> | |
1589 | if awakened by <code class="computeroutput"><span class="identifier">notify_one</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">notify_all</span><span class="special">()</span></code>, or <code class="computeroutput"><span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">timeout</span></code> | |
1590 | if awakened because the system time is past <code class="computeroutput"><span class="identifier">abs_time</span></code>. | |
1591 | </p></dd> | |
1592 | <dt><span class="term">Returns:</span></dt> | |
1593 | <dd><p> | |
1594 | The overload accepting <code class="computeroutput"><span class="identifier">pred</span></code> | |
1595 | returns <code class="computeroutput"><span class="keyword">false</span></code> if | |
1596 | the call is returning because the time specified by <code class="computeroutput"><span class="identifier">abs_time</span></code> was reached and the | |
1597 | predicate returns <code class="computeroutput"><span class="keyword">false</span></code>, | |
1598 | <code class="computeroutput"><span class="keyword">true</span></code> otherwise. | |
1599 | </p></dd> | |
1600 | <dt><span class="term">Note:</span></dt> | |
1601 | <dd><p> | |
1602 | See <span class="bold"><strong>Note</strong></span> for <a class="link" href="pooled_fixedsize.html#condition_variable_any_wait"> <code class="computeroutput">condition_variable_any::wait()</code></a>. | |
1603 | </p></dd> | |
1604 | </dl> | |
1605 | </div> | |
1606 | <p> | |
1607 | </p> | |
1608 | <h5> | |
1609 | <a name="condition_variable_any_wait_for_bridgehead"></a> | |
1610 | <span><a name="condition_variable_any_wait_for"></a></span> | |
1611 | <a class="link" href="pooled_fixedsize.html#condition_variable_any_wait_for">Templated | |
1612 | member function <code class="computeroutput">wait_for</code>()</a> | |
1613 | </h5> | |
1614 | <p> | |
1615 | </p> | |
1616 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
1617 | <span class="identifier">cv_status</span> <span class="identifier">wait_for</span><span class="special">(</span> LockType <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> | |
1618 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rel_time</span><span class="special">);</span> | |
1619 | ||
1620 | <span class="keyword">template</span><span class="special"><</span> typename LockType, typename <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Pred</span> <span class="special">></span> | |
1621 | <span class="keyword">bool</span> <span class="identifier">wait_for</span><span class="special">(</span> LockType <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> | |
1622 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rel_time</span><span class="special">,</span> | |
1623 | <span class="identifier">Pred</span> <span class="identifier">pred</span><span class="special">);</span> | |
1624 | </pre> | |
1625 | <div class="variablelist"> | |
1626 | <p class="title"><b></b></p> | |
1627 | <dl> | |
1628 | <dt><span class="term">Precondition:</span></dt> | |
1629 | <dd><p> | |
1630 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
1631 | by the current fiber, and either no other fiber is currently | |
1632 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>, | |
1633 | or the execution of the <code class="computeroutput"><span class="identifier">mutex</span><span class="special">()</span></code> member function on the <code class="computeroutput"><span class="identifier">lk</span></code> objects supplied in the | |
1634 | calls to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
1635 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
1636 | <code class="computeroutput"><span class="identifier">wait_until</span></code> in | |
1637 | all the fibers currently waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> would return the same value | |
1638 | as <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">mutex</span><span class="special">()</span></code> | |
1639 | for this call to <code class="computeroutput"><span class="identifier">wait_for</span></code>. | |
1640 | </p></dd> | |
1641 | <dt><span class="term">Effects:</span></dt> | |
1642 | <dd> | |
1643 | <p> | |
1644 | Atomically call <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">()</span></code> and blocks the current fiber. | |
1645 | The fiber will unblock when notified by a call to <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_one</span><span class="special">()</span></code> | |
1646 | or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_all</span><span class="special">()</span></code>, | |
1647 | when a time interval equal to or greater than the specified | |
1648 | <code class="computeroutput"><span class="identifier">rel_time</span></code> has | |
1649 | elapsed. When the fiber is unblocked (for whatever reason), the | |
1650 | lock is reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> before the call to <code class="computeroutput"><span class="identifier">wait</span></code> returns. The lock is also | |
1651 | reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> if the function exits with | |
1652 | an exception. The <code class="computeroutput"><span class="identifier">wait_for</span><span class="special">()</span></code> member function accepting | |
1653 | <code class="computeroutput"><span class="identifier">pred</span></code> is shorthand | |
1654 | for: | |
1655 | </p> | |
1656 | <pre class="programlisting"><span class="keyword">while</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">pred</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> | |
1657 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">timeout</span> <span class="special">==</span> <span class="identifier">wait_for</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">,</span> <span class="identifier">rel_time</span><span class="special">)</span> <span class="special">)</span> <span class="special">{</span> | |
1658 | <span class="keyword">return</span> <span class="identifier">pred</span><span class="special">();</span> | |
1659 | <span class="special">}</span> | |
1660 | <span class="special">}</span> | |
1661 | <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span> | |
1662 | </pre> | |
1663 | <p> | |
1664 | (except of course that <code class="computeroutput"><span class="identifier">rel_time</span></code> | |
1665 | is adjusted for each iteration). The point is that, even if | |
1666 | <code class="computeroutput"><span class="identifier">wait_for</span><span class="special">()</span></code> | |
1667 | times out, it can still return <code class="computeroutput"><span class="keyword">true</span></code> | |
1668 | if <code class="computeroutput"><span class="identifier">pred</span><span class="special">()</span></code> | |
1669 | returns <code class="computeroutput"><span class="keyword">true</span></code> at | |
1670 | that time. | |
1671 | </p> | |
1672 | </dd> | |
1673 | <dt><span class="term">Postcondition:</span></dt> | |
1674 | <dd><p> | |
1675 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
1676 | by the current fiber. | |
1677 | </p></dd> | |
1678 | <dt><span class="term">Throws:</span></dt> | |
1679 | <dd><p> | |
1680 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> if | |
1681 | an error occurs, <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
1682 | if the wait was interrupted by a call to <a class="link" href="../../fiber_mgmt/fiber.html#fiber_interrupt"> <code class="computeroutput">fiber::interrupt()</code></a> on | |
1683 | the <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> object associated with the current fiber | |
1684 | of execution or timeout-related exceptions. | |
1685 | </p></dd> | |
1686 | <dt><span class="term">Returns:</span></dt> | |
1687 | <dd><p> | |
1688 | The overload without <code class="computeroutput"><span class="identifier">pred</span></code> | |
1689 | returns <code class="computeroutput"><span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">no_timeout</span></code> | |
1690 | if awakened by <code class="computeroutput"><span class="identifier">notify_one</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">notify_all</span><span class="special">()</span></code>, or <code class="computeroutput"><span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">timeout</span></code> | |
1691 | if awakened because at least <code class="computeroutput"><span class="identifier">rel_time</span></code> | |
1692 | has elapsed. | |
1693 | </p></dd> | |
1694 | <dt><span class="term">Returns:</span></dt> | |
1695 | <dd><p> | |
1696 | The overload accepting <code class="computeroutput"><span class="identifier">pred</span></code> | |
1697 | returns <code class="computeroutput"><span class="keyword">false</span></code> if | |
1698 | the call is returning because at least <code class="computeroutput"><span class="identifier">rel_time</span></code> | |
1699 | has elapsed and the predicate returns <code class="computeroutput"><span class="keyword">false</span></code>, | |
1700 | <code class="computeroutput"><span class="keyword">true</span></code> otherwise. | |
1701 | </p></dd> | |
1702 | <dt><span class="term">Note:</span></dt> | |
1703 | <dd><p> | |
1704 | See <span class="bold"><strong>Note</strong></span> for <a class="link" href="pooled_fixedsize.html#condition_variable_any_wait"> <code class="computeroutput">condition_variable_any::wait()</code></a>. | |
1705 | </p></dd> | |
1706 | </dl> | |
1707 | </div> | |
1708 | <p> | |
1709 | </p> | |
1710 | <h5> | |
1711 | <a name="class_condition_variable_bridgehead"></a> | |
1712 | <span><a name="class_condition_variable"></a></span> | |
1713 | <a class="link" href="pooled_fixedsize.html#class_condition_variable">Class | |
1714 | <code class="computeroutput">condition_variable</code></a> | |
1715 | </h5> | |
1716 | <p> | |
1717 | </p> | |
1718 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">condition_variable</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
1719 | ||
1720 | <span class="keyword">class</span> condition_variable <span class="special">{</span> | |
1721 | <span class="keyword">public</span><span class="special">:</span> | |
1722 | condition_variable<span class="special">();</span> | |
1723 | <span class="special">~</span>condition_variable<span class="special">();</span> | |
1724 | ||
1725 | condition_variable<span class="special">(</span> condition_variable <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
1726 | condition_variable <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> condition_variable <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
1727 | ||
1728 | <span class="keyword">void</span> <span class="identifier">notify_one</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
1729 | <span class="keyword">void</span> <span class="identifier">notify_all</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
1730 | ||
1731 | void <span class="identifier">wait</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&);</span> | |
1732 | ||
1733 | <span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Pred</span> <span class="special">></span> | |
1734 | <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&,</span> <span class="identifier">Pred</span><span class="special">);</span> | |
1735 | ||
1736 | <span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
1737 | <span class="identifier">cv_status</span> <span class="identifier">wait_until</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&,</span> | |
1738 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&);</span> | |
1739 | ||
1740 | <span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Pred</span> <span class="special">></span> | |
1741 | <span class="keyword">bool</span> <span class="identifier">wait_until</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&,</span> | |
1742 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&,</span> | |
1743 | <span class="identifier">Pred</span><span class="special">);</span> | |
1744 | ||
1745 | <span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
1746 | <span class="identifier">cv_status</span> <span class="identifier">wait_for</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&,</span> | |
1747 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&);</span> | |
1748 | ||
1749 | <span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Pred</span> <span class="special">></span> | |
1750 | <span class="keyword">bool</span> <span class="identifier">wait_for</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&,</span> | |
1751 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&,</span> | |
1752 | <span class="identifier">Pred</span><span class="special">);</span> | |
1753 | <span class="special">};</span> | |
1754 | </pre> | |
1755 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.h7"></a> | |
1756 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.constructor0"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.constructor0">Constructor</a> | |
1757 | </h7><pre class="programlisting">condition_variable<span class="special">()</span> | |
1758 | </pre> | |
1759 | <div class="variablelist"> | |
1760 | <p class="title"><b></b></p> | |
1761 | <dl> | |
1762 | <dt><span class="term">Effects:</span></dt> | |
1763 | <dd><p> | |
1764 | Creates the object. | |
1765 | </p></dd> | |
1766 | <dt><span class="term">Throws:</span></dt> | |
1767 | <dd><p> | |
1768 | Nothing. | |
1769 | </p></dd> | |
1770 | </dl> | |
1771 | </div> | |
1772 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.h8"></a> | |
1773 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.destructor0"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.conditions.destructor0">Destructor</a> | |
1774 | </h7><pre class="programlisting"><span class="special">~</span>condition_variable<span class="special">()</span> | |
1775 | </pre> | |
1776 | <div class="variablelist"> | |
1777 | <p class="title"><b></b></p> | |
1778 | <dl> | |
1779 | <dt><span class="term">Precondition:</span></dt> | |
1780 | <dd><p> | |
1781 | All fibers waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> have been notified by a call | |
1782 | to <code class="computeroutput"><span class="identifier">notify_one</span></code> | |
1783 | or <code class="computeroutput"><span class="identifier">notify_all</span></code> | |
1784 | (though the respective calls to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
1785 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
1786 | <code class="computeroutput"><span class="identifier">wait_until</span></code> need | |
1787 | not have returned). | |
1788 | </p></dd> | |
1789 | <dt><span class="term">Effects:</span></dt> | |
1790 | <dd><p> | |
1791 | Destroys the object. | |
1792 | </p></dd> | |
1793 | </dl> | |
1794 | </div> | |
1795 | <p> | |
1796 | </p> | |
1797 | <h5> | |
1798 | <a name="condition_variable_notify_one_bridgehead"></a> | |
1799 | <span><a name="condition_variable_notify_one"></a></span> | |
1800 | <a class="link" href="pooled_fixedsize.html#condition_variable_notify_one">Member | |
1801 | function <code class="computeroutput">notify_one</code>()</a> | |
1802 | </h5> | |
1803 | <p> | |
1804 | </p> | |
1805 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">notify_one</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
1806 | </pre> | |
1807 | <div class="variablelist"> | |
1808 | <p class="title"><b></b></p> | |
1809 | <dl> | |
1810 | <dt><span class="term">Effects:</span></dt> | |
1811 | <dd><p> | |
1812 | If any fibers are currently <a class="link" href="../../overview.html#blocking"><span class="emphasis"><em>blocked</em></span></a> | |
1813 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
1814 | in a call to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
1815 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
1816 | <code class="computeroutput"><span class="identifier">wait_until</span></code>, unblocks | |
1817 | one of those fibers. | |
1818 | </p></dd> | |
1819 | <dt><span class="term">Throws:</span></dt> | |
1820 | <dd><p> | |
1821 | Nothing. | |
1822 | </p></dd> | |
1823 | <dt><span class="term">Note:</span></dt> | |
1824 | <dd><p> | |
1825 | It is arbitrary which waiting fiber is resumed. | |
1826 | </p></dd> | |
1827 | </dl> | |
1828 | </div> | |
1829 | <p> | |
1830 | </p> | |
1831 | <h5> | |
1832 | <a name="condition_variable_notify_all_bridgehead"></a> | |
1833 | <span><a name="condition_variable_notify_all"></a></span> | |
1834 | <a class="link" href="pooled_fixedsize.html#condition_variable_notify_all">Member | |
1835 | function <code class="computeroutput">notify_all</code>()</a> | |
1836 | </h5> | |
1837 | <p> | |
1838 | </p> | |
1839 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">notify_all</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
1840 | </pre> | |
1841 | <div class="variablelist"> | |
1842 | <p class="title"><b></b></p> | |
1843 | <dl> | |
1844 | <dt><span class="term">Effects:</span></dt> | |
1845 | <dd><p> | |
1846 | If any fibers are currently <a class="link" href="../../overview.html#blocking"><span class="emphasis"><em>blocked</em></span></a> | |
1847 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
1848 | in a call to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
1849 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
1850 | <code class="computeroutput"><span class="identifier">wait_until</span></code>, unblocks | |
1851 | all of those fibers. | |
1852 | </p></dd> | |
1853 | <dt><span class="term">Throws:</span></dt> | |
1854 | <dd><p> | |
1855 | Nothing. | |
1856 | </p></dd> | |
1857 | <dt><span class="term">Note:</span></dt> | |
1858 | <dd><p> | |
1859 | This is why a waiting fiber must <span class="emphasis"><em>also</em></span> check | |
1860 | for the desired program state using a mechanism external to the | |
1861 | <code class="computeroutput">condition_variable</code>, and retry the wait until that state is reached. | |
1862 | A fiber waiting on a <code class="computeroutput">condition_variable</code> might well wake up a number | |
1863 | of times before the desired state is reached. | |
1864 | </p></dd> | |
1865 | </dl> | |
1866 | </div> | |
1867 | <p> | |
1868 | </p> | |
1869 | <h5> | |
1870 | <a name="condition_variable_wait_bridgehead"></a> | |
1871 | <span><a name="condition_variable_wait"></a></span> | |
1872 | <a class="link" href="pooled_fixedsize.html#condition_variable_wait">Templated | |
1873 | member function <code class="computeroutput">wait</code>()</a> | |
1874 | </h5> | |
1875 | <p> | |
1876 | </p> | |
1877 | <pre class="programlisting">void <span class="identifier">wait</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&</span> <span class="identifier">lk</span><span class="special">);</span> | |
1878 | ||
1879 | <span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Pred</span> <span class="special">></span> | |
1880 | <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> <span class="identifier">Pred</span> <span class="identifier">pred</span><span class="special">);</span> | |
1881 | </pre> | |
1882 | <div class="variablelist"> | |
1883 | <p class="title"><b></b></p> | |
1884 | <dl> | |
1885 | <dt><span class="term">Precondition:</span></dt> | |
1886 | <dd><p> | |
1887 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
1888 | by the current fiber, and either no other fiber is currently | |
1889 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>, | |
1890 | or the execution of the <a href="http://en.cppreference.com/w/cpp/thread/unique_lock/mutex" target="_top"><code class="computeroutput"><span class="identifier">mutex</span><span class="special">()</span></code></a> | |
1891 | member function on the <code class="computeroutput"><span class="identifier">lk</span></code> | |
1892 | objects supplied in the calls to <code class="computeroutput"><span class="identifier">wait</span></code> | |
1893 | in all the fibers currently waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> would return the same value | |
1894 | as <code class="computeroutput"><span class="identifier">lk</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">()</span></code> | |
1895 | for this call to <code class="computeroutput"><span class="identifier">wait</span></code>. | |
1896 | </p></dd> | |
1897 | <dt><span class="term">Effects:</span></dt> | |
1898 | <dd> | |
1899 | <p> | |
1900 | Atomically call <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">()</span></code> and blocks the current fiber. | |
1901 | The fiber will unblock when notified by a call to <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_one</span><span class="special">()</span></code> | |
1902 | or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_all</span><span class="special">()</span></code>. | |
1903 | When the fiber is unblocked (for whatever reason), the lock is | |
1904 | reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> before the call to <code class="computeroutput"><span class="identifier">wait</span></code> returns. The lock is also | |
1905 | reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> if the function exits with | |
1906 | an exception. The member function accepting <code class="computeroutput"><span class="identifier">pred</span></code> | |
1907 | is shorthand for: | |
1908 | </p> | |
1909 | <pre class="programlisting"><span class="keyword">while</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">pred</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> | |
1910 | <span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">);</span> | |
1911 | <span class="special">}</span> | |
1912 | </pre> | |
1913 | <p> | |
1914 | </p> | |
1915 | </dd> | |
1916 | <dt><span class="term">Postcondition:</span></dt> | |
1917 | <dd><p> | |
1918 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
1919 | by the current fiber. | |
1920 | </p></dd> | |
1921 | <dt><span class="term">Throws:</span></dt> | |
1922 | <dd><p> | |
1923 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> if | |
1924 | an error occurs, <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
1925 | if the wait was interrupted by a call to <a class="link" href="../../fiber_mgmt/fiber.html#fiber_interrupt"> <code class="computeroutput">fiber::interrupt()</code></a> on | |
1926 | the <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> object associated with the current fiber | |
1927 | of execution. | |
1928 | </p></dd> | |
1929 | <dt><span class="term">Note:</span></dt> | |
1930 | <dd><p> | |
1931 | The Precondition is a bit dense. It merely states that all the | |
1932 | fibers concurrently calling <code class="computeroutput"><span class="identifier">wait</span></code> | |
1933 | on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
1934 | must wait on <code class="computeroutput"><span class="identifier">lk</span></code> | |
1935 | objects governing the <span class="emphasis"><em>same</em></span> <a class="link" href="pooled_fixedsize.html#class_mutex"> <code class="computeroutput">mutex</code></a>. | |
1936 | Three distinct objects are involved in any <code class="computeroutput">condition_variable::wait()</code> call: | |
1937 | the <code class="computeroutput">condition_variable</code> itself, the <code class="computeroutput"><span class="identifier">mutex</span></code> | |
1938 | coordinating access between fibers and a local lock object (e.g. | |
1939 | <a href="http://en.cppreference.com/w/cpp/thread/unique_lock" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span></code></a>). In general, | |
1940 | you can partition the lifespan of a given <code class="computeroutput">condition_variable</code> instance | |
1941 | into periods with one or more fibers waiting on it, separated | |
1942 | by periods when no fibers are waiting on it. When more than one | |
1943 | fiber is waiting on that <code class="computeroutput">condition_variable</code>, all must pass lock | |
1944 | objects referencing the <span class="emphasis"><em>same</em></span> <code class="computeroutput"><span class="identifier">mutex</span></code> instance. | |
1945 | </p></dd> | |
1946 | </dl> | |
1947 | </div> | |
1948 | <p> | |
1949 | </p> | |
1950 | <h5> | |
1951 | <a name="condition_variable_wait_until_bridgehead"></a> | |
1952 | <span><a name="condition_variable_wait_until"></a></span> | |
1953 | <a class="link" href="pooled_fixedsize.html#condition_variable_wait_until">Templated | |
1954 | member function <code class="computeroutput">wait_until</code>()</a> | |
1955 | </h5> | |
1956 | <p> | |
1957 | </p> | |
1958 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
1959 | <span class="identifier">cv_status</span> <span class="identifier">wait_until</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> | |
1960 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">abs_time</span><span class="special">);</span> | |
1961 | ||
1962 | <span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Pred</span> <span class="special">></span> | |
1963 | <span class="keyword">bool</span> <span class="identifier">wait_until</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> | |
1964 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">abs_time</span><span class="special">,</span> | |
1965 | <span class="identifier">Pred</span> <span class="identifier">pred</span><span class="special">);</span> | |
1966 | </pre> | |
1967 | <div class="variablelist"> | |
1968 | <p class="title"><b></b></p> | |
1969 | <dl> | |
1970 | <dt><span class="term">Precondition:</span></dt> | |
1971 | <dd><p> | |
1972 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
1973 | by the current fiber, and either no other fiber is currently | |
1974 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>, | |
1975 | or the execution of the <code class="computeroutput"><span class="identifier">mutex</span><span class="special">()</span></code> member function on the <code class="computeroutput"><span class="identifier">lk</span></code> objects supplied in the | |
1976 | calls to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
1977 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
1978 | <code class="computeroutput"><span class="identifier">wait_until</span></code> in | |
1979 | all the fibers currently waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> would return the same value | |
1980 | as <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">mutex</span><span class="special">()</span></code> | |
1981 | for this call to <code class="computeroutput"><span class="identifier">wait_until</span></code>. | |
1982 | </p></dd> | |
1983 | <dt><span class="term">Effects:</span></dt> | |
1984 | <dd> | |
1985 | <p> | |
1986 | Atomically call <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">()</span></code> and blocks the current fiber. | |
1987 | The fiber will unblock when notified by a call to <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_one</span><span class="special">()</span></code> | |
1988 | or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_all</span><span class="special">()</span></code>, | |
1989 | when the system time would be equal to or later than the specified | |
1990 | <code class="computeroutput"><span class="identifier">abs_time</span></code>. When | |
1991 | the fiber is unblocked (for whatever reason), the lock is reacquired | |
1992 | by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> before the call to <code class="computeroutput"><span class="identifier">wait_until</span></code> returns. The lock | |
1993 | is also reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> if the function exits with | |
1994 | an exception. The member function accepting <code class="computeroutput"><span class="identifier">pred</span></code> | |
1995 | is shorthand for: | |
1996 | </p> | |
1997 | <pre class="programlisting"><span class="keyword">while</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">pred</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> | |
1998 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">timeout</span> <span class="special">==</span> <span class="identifier">wait_until</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">,</span> <span class="identifier">abs_time</span><span class="special">)</span> <span class="special">)</span> | |
1999 | <span class="keyword">return</span> <span class="identifier">pred</span><span class="special">();</span> | |
2000 | <span class="special">}</span> | |
2001 | <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span> | |
2002 | </pre> | |
2003 | <p> | |
2004 | That is, even if <code class="computeroutput"><span class="identifier">wait_until</span><span class="special">()</span></code> times out, it can still return | |
2005 | <code class="computeroutput"><span class="keyword">true</span></code> if <code class="computeroutput"><span class="identifier">pred</span><span class="special">()</span></code> | |
2006 | returns <code class="computeroutput"><span class="keyword">true</span></code> at | |
2007 | that time. | |
2008 | </p> | |
2009 | </dd> | |
2010 | <dt><span class="term">Postcondition:</span></dt> | |
2011 | <dd><p> | |
2012 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
2013 | by the current fiber. | |
2014 | </p></dd> | |
2015 | <dt><span class="term">Throws:</span></dt> | |
2016 | <dd><p> | |
2017 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> if | |
2018 | an error occurs, <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
2019 | if the wait was interrupted by a call to <a class="link" href="../../fiber_mgmt/fiber.html#fiber_interrupt"> <code class="computeroutput">fiber::interrupt()</code></a> on | |
2020 | the <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> object associated with the current fiber | |
2021 | of execution or timeout-related exceptions. | |
2022 | </p></dd> | |
2023 | <dt><span class="term">Returns:</span></dt> | |
2024 | <dd><p> | |
2025 | The overload without <code class="computeroutput"><span class="identifier">pred</span></code> | |
2026 | returns <code class="computeroutput"><span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">no_timeout</span></code> | |
2027 | if awakened by <code class="computeroutput"><span class="identifier">notify_one</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">notify_all</span><span class="special">()</span></code>, or <code class="computeroutput"><span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">timeout</span></code> | |
2028 | if awakened because the system time is past <code class="computeroutput"><span class="identifier">abs_time</span></code>. | |
2029 | </p></dd> | |
2030 | <dt><span class="term">Returns:</span></dt> | |
2031 | <dd><p> | |
2032 | The overload accepting <code class="computeroutput"><span class="identifier">pred</span></code> | |
2033 | returns <code class="computeroutput"><span class="keyword">false</span></code> if | |
2034 | the call is returning because the time specified by <code class="computeroutput"><span class="identifier">abs_time</span></code> was reached and the | |
2035 | predicate returns <code class="computeroutput"><span class="keyword">false</span></code>, | |
2036 | <code class="computeroutput"><span class="keyword">true</span></code> otherwise. | |
2037 | </p></dd> | |
2038 | <dt><span class="term">Note:</span></dt> | |
2039 | <dd><p> | |
2040 | See <span class="bold"><strong>Note</strong></span> for <a class="link" href="pooled_fixedsize.html#condition_variable_wait"> <code class="computeroutput">condition_variable::wait()</code></a>. | |
2041 | </p></dd> | |
2042 | </dl> | |
2043 | </div> | |
2044 | <p> | |
2045 | </p> | |
2046 | <h5> | |
2047 | <a name="condition_variable_wait_for_bridgehead"></a> | |
2048 | <span><a name="condition_variable_wait_for"></a></span> | |
2049 | <a class="link" href="pooled_fixedsize.html#condition_variable_wait_for">Templated | |
2050 | member function <code class="computeroutput">wait_for</code>()</a> | |
2051 | </h5> | |
2052 | <p> | |
2053 | </p> | |
2054 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
2055 | <span class="identifier">cv_status</span> <span class="identifier">wait_for</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> | |
2056 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rel_time</span><span class="special">);</span> | |
2057 | ||
2058 | <span class="keyword">template</span><span class="special"><</span> typename <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Pred</span> <span class="special">></span> | |
2059 | <span class="keyword">bool</span> <span class="identifier">wait_for</span><span class="special">(</span> std::unique_lock< mutex > <span class="special">&</span> <span class="identifier">lk</span><span class="special">,</span> | |
2060 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rel_time</span><span class="special">,</span> | |
2061 | <span class="identifier">Pred</span> <span class="identifier">pred</span><span class="special">);</span> | |
2062 | </pre> | |
2063 | <div class="variablelist"> | |
2064 | <p class="title"><b></b></p> | |
2065 | <dl> | |
2066 | <dt><span class="term">Precondition:</span></dt> | |
2067 | <dd><p> | |
2068 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
2069 | by the current fiber, and either no other fiber is currently | |
2070 | waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>, | |
2071 | or the execution of the <code class="computeroutput"><span class="identifier">mutex</span><span class="special">()</span></code> member function on the <code class="computeroutput"><span class="identifier">lk</span></code> objects supplied in the | |
2072 | calls to <code class="computeroutput"><span class="identifier">wait</span></code>, | |
2073 | <code class="computeroutput"><span class="identifier">wait_for</span></code> or | |
2074 | <code class="computeroutput"><span class="identifier">wait_until</span></code> in | |
2075 | all the fibers currently waiting on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> would return the same value | |
2076 | as <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">mutex</span><span class="special">()</span></code> | |
2077 | for this call to <code class="computeroutput"><span class="identifier">wait_for</span></code>. | |
2078 | </p></dd> | |
2079 | <dt><span class="term">Effects:</span></dt> | |
2080 | <dd> | |
2081 | <p> | |
2082 | Atomically call <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">()</span></code> and blocks the current fiber. | |
2083 | The fiber will unblock when notified by a call to <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_one</span><span class="special">()</span></code> | |
2084 | or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">notify_all</span><span class="special">()</span></code>, | |
2085 | when a time interval equal to or greater than the specified | |
2086 | <code class="computeroutput"><span class="identifier">rel_time</span></code> has | |
2087 | elapsed. When the fiber is unblocked (for whatever reason), the | |
2088 | lock is reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> before the call to <code class="computeroutput"><span class="identifier">wait</span></code> returns. The lock is also | |
2089 | reacquired by invoking <code class="computeroutput"><span class="identifier">lk</span><span class="special">.</span><span class="identifier">lock</span><span class="special">()</span></code> if the function exits with | |
2090 | an exception. The <code class="computeroutput"><span class="identifier">wait_for</span><span class="special">()</span></code> member function accepting | |
2091 | <code class="computeroutput"><span class="identifier">pred</span></code> is shorthand | |
2092 | for: | |
2093 | </p> | |
2094 | <pre class="programlisting"><span class="keyword">while</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">pred</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> | |
2095 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">timeout</span> <span class="special">==</span> <span class="identifier">wait_for</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">,</span> <span class="identifier">rel_time</span><span class="special">)</span> <span class="special">)</span> <span class="special">{</span> | |
2096 | <span class="keyword">return</span> <span class="identifier">pred</span><span class="special">();</span> | |
2097 | <span class="special">}</span> | |
2098 | <span class="special">}</span> | |
2099 | <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span> | |
2100 | </pre> | |
2101 | <p> | |
2102 | (except of course that <code class="computeroutput"><span class="identifier">rel_time</span></code> | |
2103 | is adjusted for each iteration). The point is that, even if | |
2104 | <code class="computeroutput"><span class="identifier">wait_for</span><span class="special">()</span></code> | |
2105 | times out, it can still return <code class="computeroutput"><span class="keyword">true</span></code> | |
2106 | if <code class="computeroutput"><span class="identifier">pred</span><span class="special">()</span></code> | |
2107 | returns <code class="computeroutput"><span class="keyword">true</span></code> at | |
2108 | that time. | |
2109 | </p> | |
2110 | </dd> | |
2111 | <dt><span class="term">Postcondition:</span></dt> | |
2112 | <dd><p> | |
2113 | <code class="computeroutput"><span class="identifier">lk</span></code> is locked | |
2114 | by the current fiber. | |
2115 | </p></dd> | |
2116 | <dt><span class="term">Throws:</span></dt> | |
2117 | <dd><p> | |
2118 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> if | |
2119 | an error occurs, <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
2120 | if the wait was interrupted by a call to <a class="link" href="../../fiber_mgmt/fiber.html#fiber_interrupt"> <code class="computeroutput">fiber::interrupt()</code></a> on | |
2121 | the <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> object associated with the current fiber | |
2122 | of execution or timeout-related exceptions. | |
2123 | </p></dd> | |
2124 | <dt><span class="term">Returns:</span></dt> | |
2125 | <dd><p> | |
2126 | The overload without <code class="computeroutput"><span class="identifier">pred</span></code> | |
2127 | returns <code class="computeroutput"><span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">no_timeout</span></code> | |
2128 | if awakened by <code class="computeroutput"><span class="identifier">notify_one</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">notify_all</span><span class="special">()</span></code>, or <code class="computeroutput"><span class="identifier">cv_status</span><span class="special">::</span><span class="identifier">timeout</span></code> | |
2129 | if awakened because at least <code class="computeroutput"><span class="identifier">rel_time</span></code> | |
2130 | has elapsed. | |
2131 | </p></dd> | |
2132 | <dt><span class="term">Returns:</span></dt> | |
2133 | <dd><p> | |
2134 | The overload accepting <code class="computeroutput"><span class="identifier">pred</span></code> | |
2135 | returns <code class="computeroutput"><span class="keyword">false</span></code> if | |
2136 | the call is returning because at least <code class="computeroutput"><span class="identifier">rel_time</span></code> | |
2137 | has elapsed and the predicate returns <code class="computeroutput"><span class="keyword">false</span></code>, | |
2138 | <code class="computeroutput"><span class="keyword">true</span></code> otherwise. | |
2139 | </p></dd> | |
2140 | <dt><span class="term">Note:</span></dt> | |
2141 | <dd><p> | |
2142 | See <span class="bold"><strong>Note</strong></span> for <a class="link" href="pooled_fixedsize.html#condition_variable_wait"> <code class="computeroutput">condition_variable::wait()</code></a>. | |
2143 | </p></dd> | |
2144 | </dl> | |
2145 | </div> | |
2146 | </div> | |
2147 | <div class="section"> | |
2148 | <div class="titlepage"><div><div><h6 class="title"> | |
2149 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers" title="Barriers">Barriers</a> | |
2150 | </h6></div></div></div> | |
2151 | <p> | |
2152 | A barrier is a concept also known as a <span class="emphasis"><em>rendezvous</em></span>, | |
2153 | it is a synchronization point between multiple contexts of execution | |
2154 | (fibers). The barrier is configured for a particular number of fibers | |
2155 | (<code class="computeroutput"><span class="identifier">n</span></code>), and as fibers | |
2156 | reach the barrier they must wait until all <code class="computeroutput"><span class="identifier">n</span></code> | |
2157 | fibers have arrived. Once the <code class="computeroutput"><span class="identifier">n</span></code>-th | |
2158 | fiber has reached the barrier, all the waiting fibers can proceed, | |
2159 | and the barrier is reset. | |
2160 | </p> | |
2161 | <p> | |
2162 | The fact that the barrier automatically resets is significant. Consider | |
2163 | a case in which you launch some number of fibers and want to wait only | |
2164 | until the first of them has completed. You might be tempted to use | |
2165 | a <code class="computeroutput"><span class="identifier">barrier</span><span class="special">(</span><span class="number">2</span><span class="special">)</span></code> as | |
2166 | the synchronization mechanism, making each new fiber call its <a class="link" href="pooled_fixedsize.html#barrier_wait"> <code class="computeroutput">barrier::wait()</code></a> method, | |
2167 | then calling <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> | |
2168 | in the launching fiber to wait until the first other fiber completes. | |
2169 | </p> | |
2170 | <p> | |
2171 | That will in fact unblock the launching fiber. The unfortunate part | |
2172 | is that it will continue blocking the <span class="emphasis"><em>remaining</em></span> | |
2173 | fibers. | |
2174 | </p> | |
2175 | <p> | |
2176 | Consider the following scenario: | |
2177 | </p> | |
2178 | <div class="orderedlist"><ol class="orderedlist" type="1"> | |
2179 | <li class="listitem"> | |
2180 | Fiber <span class="quote">“<span class="quote">main</span>”</span> launches fibers A, B, C and D, then calls | |
2181 | <code class="computeroutput"><span class="identifier">barrier</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code>. | |
2182 | </li> | |
2183 | <li class="listitem"> | |
2184 | Fiber C finishes first and likewise calls <code class="computeroutput"><span class="identifier">barrier</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code>. | |
2185 | </li> | |
2186 | <li class="listitem"> | |
2187 | Fiber <span class="quote">“<span class="quote">main</span>”</span> is unblocked, as desired. | |
2188 | </li> | |
2189 | <li class="listitem"> | |
2190 | Fiber B calls <code class="computeroutput"><span class="identifier">barrier</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code>. Fiber B is <span class="emphasis"><em>blocked!</em></span> | |
2191 | </li> | |
2192 | <li class="listitem"> | |
2193 | Fiber A calls <code class="computeroutput"><span class="identifier">barrier</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code>. Fibers A and B are unblocked. | |
2194 | </li> | |
2195 | <li class="listitem"> | |
2196 | Fiber D calls <code class="computeroutput"><span class="identifier">barrier</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code>. Fiber D is blocked indefinitely. | |
2197 | </li> | |
2198 | </ol></div> | |
2199 | <p> | |
2200 | (See also <a class="link" href="pooled_fixedsize.html#wait_first_simple_section">when_any, simple | |
2201 | completion</a>.) | |
2202 | </p> | |
2203 | <div class="note"><table border="0" summary="Note"> | |
2204 | <tr> | |
2205 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> | |
2206 | <th align="left">Note</th> | |
2207 | </tr> | |
2208 | <tr><td align="left" valign="top"><p> | |
2209 | It is unwise to tie the lifespan of a barrier to any one of its participating | |
2210 | fibers. Although conceptually all waiting fibers awaken <span class="quote">“<span class="quote">simultaneously,</span>”</span> | |
2211 | because of the nature of fibers, in practice they will awaken one | |
2212 | by one in indeterminate order.<sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers.f0" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers.f0" class="footnote">2</a>]</sup> The rest of the waiting fibers will still be blocked | |
2213 | in <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code>, | |
2214 | which must, before returning, access data members in the barrier | |
2215 | object. | |
2216 | </p></td></tr> | |
2217 | </table></div> | |
2218 | <p> | |
2219 | </p> | |
2220 | <h5> | |
2221 | <a name="class_barrier_bridgehead"></a> | |
2222 | <span><a name="class_barrier"></a></span> | |
2223 | <a class="link" href="pooled_fixedsize.html#class_barrier">Class <code class="computeroutput">barrier</code></a> | |
2224 | </h5> | |
2225 | <p> | |
2226 | </p> | |
2227 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">barrier</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
2228 | ||
2229 | <span class="keyword">class</span> <span class="identifier">barrier</span> <span class="special">{</span> | |
2230 | <span class="keyword">public</span><span class="special">:</span> | |
2231 | <span class="keyword">explicit</span> <span class="identifier">barrier</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">);</span> | |
2232 | ||
2233 | <span class="identifier">barrier</span><span class="special">(</span> <span class="identifier">barrier</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
2234 | <span class="identifier">barrier</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">barrier</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
2235 | ||
2236 | <span class="keyword">bool</span> <span class="identifier">wait</span><span class="special">();</span> | |
2237 | <span class="special">};</span> | |
2238 | </pre> | |
2239 | <p> | |
2240 | Instances of <a class="link" href="pooled_fixedsize.html#class_barrier"> <code class="computeroutput">barrier</code></a> are not copyable or movable. | |
2241 | </p> | |
2242 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers.h0"></a> | |
2243 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers.constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers.constructor">Constructor</a> | |
2244 | </h7><pre class="programlisting"><span class="keyword">explicit</span> <span class="identifier">barrier</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">initial</span><span class="special">);</span> | |
2245 | </pre> | |
2246 | <div class="variablelist"> | |
2247 | <p class="title"><b></b></p> | |
2248 | <dl> | |
2249 | <dt><span class="term">Effects:</span></dt> | |
2250 | <dd><p> | |
2251 | Construct a barrier for <code class="computeroutput"><span class="identifier">initial</span></code> | |
2252 | fibers. | |
2253 | </p></dd> | |
2254 | <dt><span class="term">Throws:</span></dt> | |
2255 | <dd><p> | |
2256 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> | |
2257 | </p></dd> | |
2258 | <dt><span class="term">Error Conditions:</span></dt> | |
2259 | <dd><p> | |
2260 | <span class="bold"><strong>invalid_argument</strong></span>: if <code class="computeroutput"><span class="identifier">initial</span></code> is zero. | |
2261 | </p></dd> | |
2262 | </dl> | |
2263 | </div> | |
2264 | <p> | |
2265 | </p> | |
2266 | <h5> | |
2267 | <a name="barrier_wait_bridgehead"></a> | |
2268 | <span><a name="barrier_wait"></a></span> | |
2269 | <a class="link" href="pooled_fixedsize.html#barrier_wait">Member function <code class="computeroutput">wait</code>()</a> | |
2270 | </h5> | |
2271 | <p> | |
2272 | </p> | |
2273 | <pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">wait</span><span class="special">();</span> | |
2274 | </pre> | |
2275 | <div class="variablelist"> | |
2276 | <p class="title"><b></b></p> | |
2277 | <dl> | |
2278 | <dt><span class="term">Effects:</span></dt> | |
2279 | <dd><p> | |
2280 | Block until <code class="computeroutput"><span class="identifier">initial</span></code> | |
2281 | fibers have called <code class="computeroutput"><span class="identifier">wait</span></code> | |
2282 | on <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. | |
2283 | When the <code class="computeroutput"><span class="identifier">initial</span></code>-th | |
2284 | fiber calls <code class="computeroutput"><span class="identifier">wait</span></code>, | |
2285 | all waiting fibers are unblocked, and the barrier is reset. | |
2286 | </p></dd> | |
2287 | <dt><span class="term">Returns:</span></dt> | |
2288 | <dd><p> | |
2289 | <code class="computeroutput"><span class="keyword">true</span></code> for exactly | |
2290 | one fiber from each batch of waiting fibers, <code class="computeroutput"><span class="keyword">false</span></code> | |
2291 | otherwise. | |
2292 | </p></dd> | |
2293 | <dt><span class="term">Throws:</span></dt> | |
2294 | <dd><p> | |
2295 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> | |
2296 | </p></dd> | |
2297 | <dt><span class="term">Notes:</span></dt> | |
2298 | <dd><p> | |
2299 | <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> | |
2300 | is one of the predefined <a class="link" href="../../fiber_mgmt.html#interruption"><span class="emphasis"><em>interruption-points</em></span></a>. | |
2301 | </p></dd> | |
2302 | </dl> | |
2303 | </div> | |
2304 | </div> | |
2305 | <div class="section"> | |
2306 | <div class="titlepage"><div><div><h6 class="title"> | |
2307 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels" title="Channels">Channels</a> | |
2308 | </h6></div></div></div> | |
2309 | <p> | |
2310 | <span class="bold"><strong>Boost.Fiber</strong></span> provides a bounded and | |
2311 | a unbounded channel suitable to synchonize fibers via message passing. | |
2312 | </p> | |
2313 | <pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="keyword">int</span> <span class="special">></span> <span class="identifier">channel_t</span><span class="special">;</span> | |
2314 | ||
2315 | <span class="keyword">void</span> <span class="identifier">send</span><span class="special">(</span> <span class="identifier">channel_t</span> <span class="special">&</span> <span class="identifier">channel</span><span class="special">)</span> <span class="special">{</span> | |
2316 | <span class="keyword">for</span> <span class="special">(</span> <span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">5</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span> | |
2317 | <span class="identifier">channel</span><span class="special">.</span><span class="identifier">push</span><span class="special">(</span> <span class="identifier">i</span><span class="special">);</span> | |
2318 | <span class="special">}</span> | |
2319 | <span class="identifier">channel</span><span class="special">.</span><span class="identifier">close</span><span class="special">();</span> | |
2320 | <span class="special">}</span> | |
2321 | ||
2322 | <span class="keyword">void</span> <span class="identifier">recv</span><span class="special">(</span> <span class="identifier">channel_t</span> <span class="special">&</span> <span class="identifier">channel</span><span class="special">)</span> <span class="special">{</span> | |
2323 | <span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span> | |
2324 | <span class="keyword">while</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">channel_op_status</span><span class="special">::</span><span class="identifier">success</span> <span class="special">==</span> <span class="identifier">channel</span><span class="special">.</span><span class="identifier">pop</span><span class="special">(</span><span class="identifier">i</span><span class="special">)</span> <span class="special">)</span> <span class="special">{</span> | |
2325 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"received "</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
2326 | <span class="special">}</span> | |
2327 | <span class="special">}</span> | |
2328 | ||
2329 | <span class="identifier">channel_t</span> <span class="identifier">channel</span><span class="special">;</span> | |
2330 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span> <span class="identifier">f1</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span> <span class="identifier">send</span><span class="special">,</span> <span class="identifier">ref</span><span class="special">(</span> <span class="identifier">channel</span><span class="special">)</span> <span class="special">)</span> <span class="special">);</span> | |
2331 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span> <span class="identifier">f2</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span> <span class="identifier">recv</span><span class="special">,</span> <span class="identifier">ref</span><span class="special">(</span> <span class="identifier">channel</span><span class="special">)</span> <span class="special">)</span> <span class="special">);</span> | |
2332 | ||
2333 | <span class="identifier">f1</span><span class="special">.</span><span class="identifier">join</span><span class="special">();</span> | |
2334 | <span class="identifier">f2</span><span class="special">.</span><span class="identifier">join</span><span class="special">();</span> | |
2335 | </pre> | |
2336 | <a name="class_channel_op_status"></a><h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.h0"></a> | |
2337 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.enumeration__code__phrase_role__identifier__channel_op_status__phrase___code_">Enumeration | |
2338 | <code class="computeroutput"><span class="identifier">channel_op_status</span></code></a> | |
2339 | </h7><p> | |
2340 | channel operations return the state of the channel. | |
2341 | </p> | |
2342 | <pre class="programlisting"><span class="keyword">enum</span> <span class="keyword">class</span> <span class="identifier">channel_op_status</span> <span class="special">{</span> | |
2343 | <span class="identifier">success</span><span class="special">,</span> | |
2344 | <span class="identifier">empty</span><span class="special">,</span> | |
2345 | <span class="identifier">full</span><span class="special">,</span> | |
2346 | <span class="identifier">closed</span><span class="special">,</span> | |
2347 | <span class="identifier">timeout</span> | |
2348 | <span class="special">};</span> | |
2349 | </pre> | |
2350 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.h1"></a> | |
2351 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__success__phrase___code_"><code class="computeroutput"><span class="identifier">success</span></code></a> | |
2352 | </h7><div class="variablelist"> | |
2353 | <p class="title"><b></b></p> | |
2354 | <dl> | |
2355 | <dt><span class="term">Effects:</span></dt> | |
2356 | <dd><p> | |
2357 | Operation was successful. | |
2358 | </p></dd> | |
2359 | </dl> | |
2360 | </div> | |
2361 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.h2"></a> | |
2362 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__empty__phrase___code_"><code class="computeroutput"><span class="identifier">empty</span></code></a> | |
2363 | </h7><div class="variablelist"> | |
2364 | <p class="title"><b></b></p> | |
2365 | <dl> | |
2366 | <dt><span class="term">Effects:</span></dt> | |
2367 | <dd><p> | |
2368 | channel is empty, operation failed. | |
2369 | </p></dd> | |
2370 | </dl> | |
2371 | </div> | |
2372 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.h3"></a> | |
2373 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__full__phrase___code_"><code class="computeroutput"><span class="identifier">full</span></code></a> | |
2374 | </h7><div class="variablelist"> | |
2375 | <p class="title"><b></b></p> | |
2376 | <dl> | |
2377 | <dt><span class="term">Effects:</span></dt> | |
2378 | <dd><p> | |
2379 | channel is full, operation failed. | |
2380 | </p></dd> | |
2381 | </dl> | |
2382 | </div> | |
2383 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.h4"></a> | |
2384 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__closed__phrase___code_"><code class="computeroutput"><span class="identifier">closed</span></code></a> | |
2385 | </h7><div class="variablelist"> | |
2386 | <p class="title"><b></b></p> | |
2387 | <dl> | |
2388 | <dt><span class="term">Effects:</span></dt> | |
2389 | <dd><p> | |
2390 | channel is closed, operation failed. | |
2391 | </p></dd> | |
2392 | </dl> | |
2393 | </div> | |
2394 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.h5"></a> | |
2395 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels._code__phrase_role__identifier__timeout__phrase___code_"><code class="computeroutput"><span class="identifier">timeout</span></code></a> | |
2396 | </h7><div class="variablelist"> | |
2397 | <p class="title"><b></b></p> | |
2398 | <dl> | |
2399 | <dt><span class="term">Effects:</span></dt> | |
2400 | <dd><p> | |
2401 | The operation did not become ready before specified timeout elapsed. | |
2402 | </p></dd> | |
2403 | </dl> | |
2404 | </div> | |
2405 | <p> | |
2406 | </p> | |
2407 | <h5> | |
2408 | <a name="class_unbounded_channel_bridgehead"></a> | |
2409 | <span><a name="class_unbounded_channel"></a></span> | |
2410 | <a class="link" href="pooled_fixedsize.html#class_unbounded_channel">Template | |
2411 | <code class="computeroutput">unbounded_channel<></code></a> | |
2412 | </h5> | |
2413 | <p> | |
2414 | </p> | |
2415 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">unbounded_channel</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
2416 | ||
2417 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="special">=</span> <a href="http://en.cppreference.com/w/cpp/memory/allocator" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><</span> <span class="identifier">T</span> <span class="special">></span></code></a> <span class="special">></span> | |
2418 | <span class="keyword">class</span> <span class="identifier">unbounded_channel</span> <span class="special">{</span> | |
2419 | <span class="keyword">public</span><span class="special">:</span> | |
2420 | <span class="keyword">typedef</span> <span class="identifier">T</span> <span class="identifier">value_type</span><span class="special">;</span> | |
2421 | ||
2422 | <span class="keyword">explicit</span> <span class="identifier">unbounded_channel</span><span class="special">(</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">alloc</span> <span class="special">=</span> <span class="identifier">Allocator</span><span class="special">()</span> <span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2423 | ||
2424 | <span class="identifier">unbounded_channel</span><span class="special">(</span> <span class="identifier">unbounded_channel</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
2425 | <span class="identifier">unbounded_channel</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">unbounded_channel</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
2426 | ||
2427 | <span class="keyword">void</span> <span class="identifier">close</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2428 | ||
2429 | <span class="identifier">channel_op_status</span> <span class="identifier">push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2430 | <span class="identifier">channel_op_status</span> <span class="identifier">push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">);</span> | |
2431 | ||
2432 | <span class="identifier">channel_op_status</span> <span class="identifier">pop</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2433 | <span class="identifier">value_type</span> <span class="identifier">value_pop</span><span class="special">();</span> | |
2434 | <span class="identifier">channel_op_status</span> <span class="identifier">try_pop</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2435 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
2436 | <span class="identifier">channel_op_status</span> <span class="identifier">pop_wait_for</span><span class="special">(</span> | |
2437 | <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2438 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
2439 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
2440 | <span class="identifier">channel_op_status</span> <span class="identifier">pop_wait_until</span><span class="special">(</span> | |
2441 | <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2442 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
2443 | <span class="special">};</span> | |
2444 | </pre> | |
2445 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.h6"></a> | |
2446 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.constructor">Constructor</a> | |
2447 | </h7><pre class="programlisting"><span class="keyword">explicit</span> <span class="identifier">unbounded_channel</span><span class="special">(</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">alloc</span> <span class="special">=</span> <span class="identifier">Allocator</span><span class="special">()</span> <span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2448 | </pre> | |
2449 | <div class="variablelist"> | |
2450 | <p class="title"><b></b></p> | |
2451 | <dl> | |
2452 | <dt><span class="term">Effects:</span></dt> | |
2453 | <dd><p> | |
2454 | Constructs an object of class <code class="computeroutput"><span class="identifier">unbounded_channel</span></code>. | |
2455 | Internal nodes are allocated using <code class="computeroutput"><span class="identifier">alloc</span></code> | |
2456 | - C++11-allocators are supported. | |
2457 | </p></dd> | |
2458 | <dt><span class="term">Throws:</span></dt> | |
2459 | <dd><p> | |
2460 | Nothing. | |
2461 | </p></dd> | |
2462 | <dt><span class="term">See also:</span></dt> | |
2463 | <dd><p> | |
2464 | <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> concept, | |
2465 | <a href="http://en.cppreference.com/w/cpp/memory/allocator" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><</span> | |
2466 | <span class="identifier">T</span> <span class="special">></span></code></a> | |
2467 | </p></dd> | |
2468 | </dl> | |
2469 | </div> | |
2470 | <p> | |
2471 | </p> | |
2472 | <h5> | |
2473 | <a name="unbounded_channel_close_bridgehead"></a> | |
2474 | <span><a name="unbounded_channel_close"></a></span> | |
2475 | <a class="link" href="pooled_fixedsize.html#unbounded_channel_close">Member | |
2476 | function <code class="computeroutput">close</code>()</a> | |
2477 | </h5> | |
2478 | <p> | |
2479 | </p> | |
2480 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">close</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2481 | </pre> | |
2482 | <div class="variablelist"> | |
2483 | <p class="title"><b></b></p> | |
2484 | <dl> | |
2485 | <dt><span class="term">Effects:</span></dt> | |
2486 | <dd><p> | |
2487 | Deactivates the channel. No values can be put after calling | |
2488 | <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">close</span><span class="special">()</span></code>. | |
2489 | Fibers blocked in <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_until</span><span class="special">()</span></code> will return <code class="computeroutput"><span class="identifier">closed</span></code>. | |
2490 | Fibers blocked in <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span></code> will receive an exception. | |
2491 | </p></dd> | |
2492 | <dt><span class="term">Throws:</span></dt> | |
2493 | <dd><p> | |
2494 | Nothing. | |
2495 | </p></dd> | |
2496 | <dt><span class="term">Note:</span></dt> | |
2497 | <dd><p> | |
2498 | <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code> | |
2499 | is like closing a pipe. It informs waiting consumers that no | |
2500 | more values will arrive. | |
2501 | </p></dd> | |
2502 | </dl> | |
2503 | </div> | |
2504 | <p> | |
2505 | </p> | |
2506 | <h5> | |
2507 | <a name="unbounded_channel_push_bridgehead"></a> | |
2508 | <span><a name="unbounded_channel_push"></a></span> | |
2509 | <a class="link" href="pooled_fixedsize.html#unbounded_channel_push">Member | |
2510 | function <code class="computeroutput">push</code>()</a> | |
2511 | </h5> | |
2512 | <p> | |
2513 | </p> | |
2514 | <pre class="programlisting"><span class="identifier">channel_op_status</span> <span class="identifier">push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2515 | <span class="identifier">channel_op_status</span> <span class="identifier">push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">);</span> | |
2516 | </pre> | |
2517 | <div class="variablelist"> | |
2518 | <p class="title"><b></b></p> | |
2519 | <dl> | |
2520 | <dt><span class="term">Effects:</span></dt> | |
2521 | <dd><p> | |
2522 | If channel is closed, returns <code class="computeroutput"><span class="identifier">closed</span></code>. | |
2523 | Otherwise enqueues the value in the channel, wakes up a fiber | |
2524 | blocked on <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_until</span><span class="special">()</span></code> and returns <code class="computeroutput"><span class="identifier">success</span></code>. | |
2525 | </p></dd> | |
2526 | <dt><span class="term">Throws:</span></dt> | |
2527 | <dd><p> | |
2528 | Exceptions thrown by memory allocation and copying or moving | |
2529 | <code class="computeroutput"><span class="identifier">va</span></code>. | |
2530 | </p></dd> | |
2531 | </dl> | |
2532 | </div> | |
2533 | <p> | |
2534 | </p> | |
2535 | <h5> | |
2536 | <a name="unbounded_channel_pop_bridgehead"></a> | |
2537 | <span><a name="unbounded_channel_pop"></a></span> | |
2538 | <a class="link" href="pooled_fixedsize.html#unbounded_channel_pop">Member | |
2539 | function <code class="computeroutput">pop</code>()</a> | |
2540 | </h5> | |
2541 | <p> | |
2542 | </p> | |
2543 | <pre class="programlisting"><span class="identifier">channel_op_status</span> <span class="identifier">pop</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2544 | </pre> | |
2545 | <div class="variablelist"> | |
2546 | <p class="title"><b></b></p> | |
2547 | <dl> | |
2548 | <dt><span class="term">Effects:</span></dt> | |
2549 | <dd><p> | |
2550 | Dequeues a value from the channel. If the channel is empty, the | |
2551 | fiber gets suspended until at least one new item is <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>ed | |
2552 | (return value <code class="computeroutput"><span class="identifier">success</span></code> | |
2553 | and <code class="computeroutput"><span class="identifier">va</span></code> contains | |
2554 | dequeued value) or the channel gets <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (return value <code class="computeroutput"><span class="identifier">closed</span></code>). | |
2555 | </p></dd> | |
2556 | <dt><span class="term">Throws:</span></dt> | |
2557 | <dd><p> | |
2558 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
2559 | </p></dd> | |
2560 | </dl> | |
2561 | </div> | |
2562 | <p> | |
2563 | </p> | |
2564 | <h5> | |
2565 | <a name="unbounded_channel_value_pop_bridgehead"></a> | |
2566 | <span><a name="unbounded_channel_value_pop"></a></span> | |
2567 | <a class="link" href="pooled_fixedsize.html#unbounded_channel_value_pop">Member | |
2568 | function <code class="computeroutput">value_pop</code>()</a> | |
2569 | </h5> | |
2570 | <p> | |
2571 | </p> | |
2572 | <pre class="programlisting"><span class="identifier">value_type</span> <span class="identifier">value_pop</span><span class="special">();</span> | |
2573 | </pre> | |
2574 | <div class="variablelist"> | |
2575 | <p class="title"><b></b></p> | |
2576 | <dl> | |
2577 | <dt><span class="term">Effects:</span></dt> | |
2578 | <dd><p> | |
2579 | Dequeues a value from the channel. If the channel is empty, the | |
2580 | fiber gets suspended until at least one new item is <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>ed | |
2581 | or the channel gets <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (which throws an exception). | |
2582 | </p></dd> | |
2583 | <dt><span class="term">Throws:</span></dt> | |
2584 | <dd><p> | |
2585 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> if | |
2586 | <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
2587 | is closed or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
2588 | </p></dd> | |
2589 | <dt><span class="term">Error conditions:</span></dt> | |
2590 | <dd><p> | |
2591 | <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">errc</span><span class="special">::</span><span class="identifier">operation_not_permitted</span></code> | |
2592 | </p></dd> | |
2593 | </dl> | |
2594 | </div> | |
2595 | <p> | |
2596 | </p> | |
2597 | <h5> | |
2598 | <a name="unbounded_channel_try_pop_bridgehead"></a> | |
2599 | <span><a name="unbounded_channel_try_pop"></a></span> | |
2600 | <a class="link" href="pooled_fixedsize.html#unbounded_channel_try_pop">Member | |
2601 | function <code class="computeroutput">try_pop</code>()</a> | |
2602 | </h5> | |
2603 | <p> | |
2604 | </p> | |
2605 | <pre class="programlisting"><span class="identifier">channel_op_status</span> <span class="identifier">try_pop</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2606 | </pre> | |
2607 | <div class="variablelist"> | |
2608 | <p class="title"><b></b></p> | |
2609 | <dl> | |
2610 | <dt><span class="term">Effects:</span></dt> | |
2611 | <dd><p> | |
2612 | If channel is empty, returns <code class="computeroutput"><span class="identifier">empty</span></code>. | |
2613 | If channel is closed, returns <code class="computeroutput"><span class="identifier">closed</span></code>. | |
2614 | Otherwise it returns <code class="computeroutput"><span class="identifier">success</span></code> | |
2615 | and <code class="computeroutput"><span class="identifier">va</span></code> contains | |
2616 | the dequeued value. | |
2617 | </p></dd> | |
2618 | <dt><span class="term">Throws:</span></dt> | |
2619 | <dd><p> | |
2620 | Exceptions thrown by copy- or move-operations. | |
2621 | </p></dd> | |
2622 | </dl> | |
2623 | </div> | |
2624 | <p> | |
2625 | </p> | |
2626 | <h5> | |
2627 | <a name="unbounded_channel_pop_wait_for_bridgehead"></a> | |
2628 | <span><a name="unbounded_channel_pop_wait_for"></a></span> | |
2629 | <a class="link" href="pooled_fixedsize.html#unbounded_channel_pop_wait_for">Member | |
2630 | function <code class="computeroutput">pop_wait_for</code>()</a> | |
2631 | </h5> | |
2632 | <p> | |
2633 | </p> | |
2634 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
2635 | <span class="identifier">channel_op_status</span> <span class="identifier">pop_wait_for</span><span class="special">(</span> | |
2636 | <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2637 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">)</span> | |
2638 | </pre> | |
2639 | <div class="variablelist"> | |
2640 | <p class="title"><b></b></p> | |
2641 | <dl> | |
2642 | <dt><span class="term">Effects:</span></dt> | |
2643 | <dd><p> | |
2644 | Accepts <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span></code> and internally computes | |
2645 | a timeout time as (system time + <code class="computeroutput"><span class="identifier">timeout_duration</span></code>). | |
2646 | If channel is not empty, immediately dequeues a value from the | |
2647 | channel. Otherwise the fiber gets suspended until at least one | |
2648 | new item is <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>ed (return value <code class="computeroutput"><span class="identifier">success</span></code> and <code class="computeroutput"><span class="identifier">va</span></code> | |
2649 | contains dequeued value), or the channel gets <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (return value <code class="computeroutput"><span class="identifier">closed</span></code>), or the system time | |
2650 | reaches the computed timeout time (return value <code class="computeroutput"><span class="identifier">timeout</span></code>). | |
2651 | </p></dd> | |
2652 | <dt><span class="term">Throws:</span></dt> | |
2653 | <dd><p> | |
2654 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
2655 | or timeout-related exceptions. | |
2656 | </p></dd> | |
2657 | </dl> | |
2658 | </div> | |
2659 | <p> | |
2660 | </p> | |
2661 | <h5> | |
2662 | <a name="unbounded_channel_pop_wait_until_bridgehead"></a> | |
2663 | <span><a name="unbounded_channel_pop_wait_until"></a></span> | |
2664 | <a class="link" href="pooled_fixedsize.html#unbounded_channel_pop_wait_until">Member | |
2665 | function <code class="computeroutput">pop_wait_until</code>()</a> | |
2666 | </h5> | |
2667 | <p> | |
2668 | </p> | |
2669 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
2670 | <span class="identifier">channel_op_status</span> <span class="identifier">pop_wait_until</span><span class="special">(</span> | |
2671 | <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2672 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">)</span> | |
2673 | </pre> | |
2674 | <div class="variablelist"> | |
2675 | <p class="title"><b></b></p> | |
2676 | <dl> | |
2677 | <dt><span class="term">Effects:</span></dt> | |
2678 | <dd><p> | |
2679 | Accepts a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> | |
2680 | <span class="special">></span></code>. If channel is not | |
2681 | empty, immediately dequeues a value from the channel. Otherwise | |
2682 | the fiber gets suspended until at least one new item is <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>ed | |
2683 | (return value <code class="computeroutput"><span class="identifier">success</span></code> | |
2684 | and <code class="computeroutput"><span class="identifier">va</span></code> contains | |
2685 | dequeued value), or the channel gets <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (return value <code class="computeroutput"><span class="identifier">closed</span></code>), or the system time | |
2686 | reaches the passed <code class="computeroutput"><span class="identifier">time_point</span></code> | |
2687 | (return value <code class="computeroutput"><span class="identifier">timeout</span></code>). | |
2688 | </p></dd> | |
2689 | <dt><span class="term">Throws:</span></dt> | |
2690 | <dd><p> | |
2691 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
2692 | or timeout-related exceptions. | |
2693 | </p></dd> | |
2694 | </dl> | |
2695 | </div> | |
2696 | <p> | |
2697 | </p> | |
2698 | <h5> | |
2699 | <a name="class_bounded_channel_bridgehead"></a> | |
2700 | <span><a name="class_bounded_channel"></a></span> | |
2701 | <a class="link" href="pooled_fixedsize.html#class_bounded_channel">Template | |
2702 | <code class="computeroutput">bounded_channel<></code></a> | |
2703 | </h5> | |
2704 | <p> | |
2705 | </p> | |
2706 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">bounded_channel</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
2707 | ||
2708 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="special">=</span> <a href="http://en.cppreference.com/w/cpp/memory/allocator" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><</span> <span class="identifier">T</span> <span class="special">></span></code></a> <span class="special">></span> | |
2709 | <span class="keyword">class</span> <span class="identifier">bounded_channel</span> <span class="special">{</span> | |
2710 | <span class="keyword">public</span><span class="special">:</span> | |
2711 | <span class="keyword">typedef</span> <span class="identifier">T</span> <span class="identifier">value_type</span><span class="special">;</span> | |
2712 | ||
2713 | <span class="identifier">bounded_channel</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">wm</span><span class="special">,</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">alloc</span> <span class="special">=</span> <span class="identifier">Allocator</span><span class="special">()</span> <span class="special">);</span> | |
2714 | <span class="identifier">bounded_channel</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">hwm</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">lwm</span><span class="special">,</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">alloc</span> <span class="special">=</span> <span class="identifier">Allocator</span><span class="special">()</span> <span class="special">);</span> | |
2715 | ||
2716 | <span class="identifier">bounded_channel</span><span class="special">(</span> <span class="identifier">bounded_channel</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
2717 | <span class="identifier">bounded_channel</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">bounded_channel</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
2718 | ||
2719 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">upper_bound</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2720 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">lower_bound</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2721 | ||
2722 | <span class="keyword">void</span> <span class="identifier">close</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2723 | ||
2724 | <span class="identifier">channel_op_status</span> <span class="identifier">push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2725 | <span class="identifier">channel_op_status</span> <span class="identifier">push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">);</span> | |
2726 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
2727 | <span class="identifier">channel_op_status</span> <span class="identifier">push_wait_for</span><span class="special">(</span> | |
2728 | <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2729 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
2730 | <span class="identifier">channel_op_status</span> <span class="identifier">push_wait_for</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">,</span> | |
2731 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
2732 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
2733 | <span class="identifier">channel_op_status</span> <span class="identifier">push_wait_until</span><span class="special">(</span> | |
2734 | <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2735 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
2736 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
2737 | <span class="identifier">channel_op_status</span> <span class="identifier">push_wait_until</span><span class="special">(</span> | |
2738 | <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">,</span> | |
2739 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
2740 | <span class="identifier">channel_op_status</span> <span class="identifier">try_push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2741 | <span class="identifier">channel_op_status</span> <span class="identifier">try_push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">);</span> | |
2742 | ||
2743 | <span class="identifier">channel_op_status</span> <span class="identifier">pop</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2744 | <span class="identifier">value_type</span> <span class="identifier">value_pop</span><span class="special">();</span> | |
2745 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
2746 | <span class="identifier">channel_op_status</span> <span class="identifier">pop_wait_for</span><span class="special">(</span> | |
2747 | <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2748 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
2749 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
2750 | <span class="identifier">channel_op_status</span> <span class="identifier">pop_wait_until</span><span class="special">(</span> | |
2751 | <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2752 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
2753 | <span class="identifier">channel_op_status</span> <span class="identifier">try_pop</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2754 | <span class="special">};</span> | |
2755 | </pre> | |
2756 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.h7"></a> | |
2757 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.constructor0"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.channels.constructor0">Constructor</a> | |
2758 | </h7><pre class="programlisting"><span class="identifier">bounded_channel</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">wm</span><span class="special">,</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">alloc</span> <span class="special">=</span> <span class="identifier">Allocator</span><span class="special">()</span> <span class="special">);</span> | |
2759 | <span class="identifier">bounded_channel</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">hwm</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">lwm</span><span class="special">,</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">alloc</span> <span class="special">=</span> <span class="identifier">Allocator</span><span class="special">()</span> <span class="special">);</span> | |
2760 | </pre> | |
2761 | <div class="variablelist"> | |
2762 | <p class="title"><b></b></p> | |
2763 | <dl> | |
2764 | <dt><span class="term">Preconditions:</span></dt> | |
2765 | <dd><p> | |
2766 | <code class="computeroutput"><span class="identifier">hwm</span> <span class="special">></span> | |
2767 | <span class="identifier">lwm</span></code> | |
2768 | </p></dd> | |
2769 | <dt><span class="term">Effects:</span></dt> | |
2770 | <dd><p> | |
2771 | Constructs an object of class <code class="computeroutput"><span class="identifier">bounded_channel</span></code>. | |
2772 | The constructor with two arguments constructs an object of class | |
2773 | <code class="computeroutput"><span class="identifier">bounded_channel</span></code> | |
2774 | with a high-watermark of <code class="computeroutput"><span class="identifier">hwm</span></code> | |
2775 | and a low-watermark of <code class="computeroutput"><span class="identifier">lwm</span></code> | |
2776 | items. The constructor with one <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span></code> | |
2777 | argument is effectively the same as <code class="computeroutput"><span class="identifier">bounded_channel</span><span class="special">(</span><span class="identifier">wm</span><span class="special">,</span> <span class="special">(</span><span class="identifier">wm</span><span class="special">-</span><span class="number">1</span><span class="special">),</span> <span class="identifier">alloc</span><span class="special">)</span></code>. | |
2778 | Internal nodes are allocated using <code class="computeroutput"><span class="identifier">alloc</span></code> | |
2779 | - C++11-allocators are supported. | |
2780 | </p></dd> | |
2781 | <dt><span class="term">Throws:</span></dt> | |
2782 | <dd><p> | |
2783 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> | |
2784 | </p></dd> | |
2785 | <dt><span class="term">Error Conditions:</span></dt> | |
2786 | <dd><p> | |
2787 | <span class="bold"><strong>invalid_argument</strong></span>: if <code class="computeroutput"><span class="identifier">lwm</span> <span class="special">>=</span> | |
2788 | <span class="identifier">hwm</span></code>. | |
2789 | </p></dd> | |
2790 | <dt><span class="term">Notes:</span></dt> | |
2791 | <dd><p> | |
2792 | Once the number of values in the channel reaches <code class="computeroutput"><span class="identifier">hwm</span></code>, any call to <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>, | |
2793 | <code class="computeroutput"><span class="identifier">push_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">push_wait_until</span><span class="special">()</span></code> will block until the number | |
2794 | of values in the channel is at most <code class="computeroutput"><span class="identifier">lwm</span></code>. | |
2795 | That is, if <code class="computeroutput"><span class="identifier">lwm</span> <span class="special"><</span> <span class="special">(</span><span class="identifier">hwm</span><span class="special">-</span><span class="number">1</span><span class="special">)</span></code>, | |
2796 | the channel can be in a state in which <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">push_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">push_wait_until</span><span class="special">()</span></code> calls will block (channel is | |
2797 | full) even though the number of values in the channel is less | |
2798 | than <code class="computeroutput"><span class="identifier">hwm</span></code>. | |
2799 | </p></dd> | |
2800 | <dt><span class="term">See also:</span></dt> | |
2801 | <dd><p> | |
2802 | <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> concept, | |
2803 | <a href="http://en.cppreference.com/w/cpp/memory/allocator" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><</span> | |
2804 | <span class="identifier">T</span> <span class="special">></span></code></a> | |
2805 | </p></dd> | |
2806 | </dl> | |
2807 | </div> | |
2808 | <p> | |
2809 | </p> | |
2810 | <h5> | |
2811 | <a name="bounded_channel_upper_bound_bridgehead"></a> | |
2812 | <span><a name="bounded_channel_upper_bound"></a></span> | |
2813 | <a class="link" href="pooled_fixedsize.html#bounded_channel_upper_bound">Member | |
2814 | function <code class="computeroutput">upper_bound</code>()</a> | |
2815 | </h5> | |
2816 | <p> | |
2817 | </p> | |
2818 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">upper_bound</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2819 | </pre> | |
2820 | <div class="variablelist"> | |
2821 | <p class="title"><b></b></p> | |
2822 | <dl> | |
2823 | <dt><span class="term">Returns:</span></dt> | |
2824 | <dd><p> | |
2825 | the high-watermark with which <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> was constructed. | |
2826 | </p></dd> | |
2827 | <dt><span class="term">Throws:</span></dt> | |
2828 | <dd><p> | |
2829 | Nothing. | |
2830 | </p></dd> | |
2831 | </dl> | |
2832 | </div> | |
2833 | <p> | |
2834 | </p> | |
2835 | <h5> | |
2836 | <a name="bounded_channel_lower_bound_bridgehead"></a> | |
2837 | <span><a name="bounded_channel_lower_bound"></a></span> | |
2838 | <a class="link" href="pooled_fixedsize.html#bounded_channel_lower_bound">Member | |
2839 | function <code class="computeroutput">lower_bound</code>()</a> | |
2840 | </h5> | |
2841 | <p> | |
2842 | </p> | |
2843 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">lower_bound</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2844 | </pre> | |
2845 | <div class="variablelist"> | |
2846 | <p class="title"><b></b></p> | |
2847 | <dl> | |
2848 | <dt><span class="term">Returns:</span></dt> | |
2849 | <dd><p> | |
2850 | the low-watermark with which <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> was constructed. | |
2851 | </p></dd> | |
2852 | <dt><span class="term">Throws:</span></dt> | |
2853 | <dd><p> | |
2854 | Nothing. | |
2855 | </p></dd> | |
2856 | </dl> | |
2857 | </div> | |
2858 | <p> | |
2859 | </p> | |
2860 | <h5> | |
2861 | <a name="bounded_channel_close_bridgehead"></a> | |
2862 | <span><a name="bounded_channel_close"></a></span> | |
2863 | <a class="link" href="pooled_fixedsize.html#bounded_channel_close">Member | |
2864 | function <code class="computeroutput">close</code>()</a> | |
2865 | </h5> | |
2866 | <p> | |
2867 | </p> | |
2868 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">close</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
2869 | </pre> | |
2870 | <div class="variablelist"> | |
2871 | <p class="title"><b></b></p> | |
2872 | <dl> | |
2873 | <dt><span class="term">Effects:</span></dt> | |
2874 | <dd><p> | |
2875 | Deactivates the channel. No values can be put after calling | |
2876 | <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">close</span><span class="special">()</span></code>. | |
2877 | Fibers blocked in <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_until</span><span class="special">()</span></code> will return <code class="computeroutput"><span class="identifier">closed</span></code>. | |
2878 | Fibers blocked in <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span></code> will receive an exception. | |
2879 | </p></dd> | |
2880 | <dt><span class="term">Throws:</span></dt> | |
2881 | <dd><p> | |
2882 | Nothing. | |
2883 | </p></dd> | |
2884 | <dt><span class="term">Note:</span></dt> | |
2885 | <dd><p> | |
2886 | <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code> | |
2887 | is like closing a pipe. It informs waiting consumers that no | |
2888 | more values will arrive. | |
2889 | </p></dd> | |
2890 | </dl> | |
2891 | </div> | |
2892 | <p> | |
2893 | </p> | |
2894 | <h5> | |
2895 | <a name="bounded_channel_push_bridgehead"></a> | |
2896 | <span><a name="bounded_channel_push"></a></span> | |
2897 | <a class="link" href="pooled_fixedsize.html#bounded_channel_push">Member | |
2898 | function <code class="computeroutput">push</code>()</a> | |
2899 | </h5> | |
2900 | <p> | |
2901 | </p> | |
2902 | <pre class="programlisting"><span class="identifier">channel_op_status</span> <span class="identifier">push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
2903 | <span class="identifier">channel_op_status</span> <span class="identifier">push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">);</span> | |
2904 | </pre> | |
2905 | <div class="variablelist"> | |
2906 | <p class="title"><b></b></p> | |
2907 | <dl> | |
2908 | <dt><span class="term">Effects:</span></dt> | |
2909 | <dd><p> | |
2910 | If channel is closed, returns <code class="computeroutput"><span class="identifier">closed</span></code>. | |
2911 | If channel is not full, enqueues the value in the channel, wakes | |
2912 | up a fiber blocked on <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_until</span><span class="special">()</span></code> and returns <code class="computeroutput"><span class="identifier">success</span></code>. | |
2913 | Otherwise the calling fiber is suspended until the number of | |
2914 | values in the channel drops to <code class="computeroutput"><span class="identifier">lwm</span></code> | |
2915 | (return value <code class="computeroutput"><span class="identifier">success</span></code>)or | |
2916 | the channel is <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (return value <code class="computeroutput"><span class="identifier">closed</span></code>). | |
2917 | </p></dd> | |
2918 | <dt><span class="term">Throws:</span></dt> | |
2919 | <dd><p> | |
2920 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
2921 | or exceptions thrown by memory allocation and copying or moving | |
2922 | <code class="computeroutput"><span class="identifier">va</span></code>. | |
2923 | </p></dd> | |
2924 | </dl> | |
2925 | </div> | |
2926 | <p> | |
2927 | </p> | |
2928 | <h5> | |
2929 | <a name="bounded_channel_push_wait_for_bridgehead"></a> | |
2930 | <span><a name="bounded_channel_push_wait_for"></a></span> | |
2931 | <a class="link" href="pooled_fixedsize.html#bounded_channel_push_wait_for">Member | |
2932 | function <code class="computeroutput">push_wait_for</code>()</a> | |
2933 | </h5> | |
2934 | <p> | |
2935 | </p> | |
2936 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
2937 | <span class="identifier">channel_op_status</span> <span class="identifier">push_wait_for</span><span class="special">(</span> | |
2938 | <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2939 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
2940 | ||
2941 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
2942 | <span class="identifier">channel_op_status</span> <span class="identifier">push_wait_for</span><span class="special">(</span> | |
2943 | <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">,</span> | |
2944 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">);</span> | |
2945 | </pre> | |
2946 | <div class="variablelist"> | |
2947 | <p class="title"><b></b></p> | |
2948 | <dl> | |
2949 | <dt><span class="term">Effects:</span></dt> | |
2950 | <dd><p> | |
2951 | Accepts <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span></code> and internally computes | |
2952 | a time_point as (system time + <code class="computeroutput"><span class="identifier">timeout_duration</span></code>). | |
2953 | If channel is closed, returns <code class="computeroutput"><span class="identifier">closed</span></code>. | |
2954 | If channel is not full, enqueues the value in the channel, wakes | |
2955 | up a fiber blocked on <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_until</span><span class="special">()</span></code> and returns <code class="computeroutput"><span class="identifier">success</span></code>. | |
2956 | Otherwise the calling fiber is suspended until the number of | |
2957 | values in the channel drops to <code class="computeroutput"><span class="identifier">lwm</span></code> | |
2958 | (return value <code class="computeroutput"><span class="identifier">success</span></code>), | |
2959 | the channel is <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (return value <code class="computeroutput"><span class="identifier">closed</span></code>), or the system time | |
2960 | reaches the computed time_point (return value <code class="computeroutput"><span class="identifier">timeout</span></code>). | |
2961 | </p></dd> | |
2962 | <dt><span class="term">Throws:</span></dt> | |
2963 | <dd><p> | |
2964 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code>, | |
2965 | exceptions thrown by memory allocation and copying or moving | |
2966 | <code class="computeroutput"><span class="identifier">va</span></code> or timeout-related | |
2967 | exceptions. | |
2968 | </p></dd> | |
2969 | </dl> | |
2970 | </div> | |
2971 | <p> | |
2972 | </p> | |
2973 | <h5> | |
2974 | <a name="bounded_channel_push_wait_until_bridgehead"></a> | |
2975 | <span><a name="bounded_channel_push_wait_until"></a></span> | |
2976 | <a class="link" href="pooled_fixedsize.html#bounded_channel_push_wait_until">Member | |
2977 | function <code class="computeroutput">push_wait_until</code>()</a> | |
2978 | </h5> | |
2979 | <p> | |
2980 | </p> | |
2981 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
2982 | <span class="identifier">channel_op_status</span> <span class="identifier">push_wait_until</span><span class="special">(</span> | |
2983 | <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
2984 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
2985 | ||
2986 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
2987 | <span class="identifier">channel_op_status</span> <span class="identifier">push_wait_until</span><span class="special">(</span> | |
2988 | <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">,</span> | |
2989 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">);</span> | |
2990 | </pre> | |
2991 | <div class="variablelist"> | |
2992 | <p class="title"><b></b></p> | |
2993 | <dl> | |
2994 | <dt><span class="term">Effects:</span></dt> | |
2995 | <dd><p> | |
2996 | Accepts an absolute <code class="computeroutput"><span class="identifier">timeout_time</span></code> | |
2997 | in any supported time_point type. If channel is closed, returns | |
2998 | <code class="computeroutput"><span class="identifier">closed</span></code>. If channel | |
2999 | is not full, enqueues the value in the channel, wakes up a fiber | |
3000 | blocked on <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_until</span><span class="special">()</span></code> and returns <code class="computeroutput"><span class="identifier">success</span></code>. | |
3001 | Otherwise the calling fiber is suspended until the number of | |
3002 | values in the channel drops to <code class="computeroutput"><span class="identifier">lwm</span></code> | |
3003 | (return value <code class="computeroutput"><span class="identifier">success</span></code>), | |
3004 | the channel is <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (return value <code class="computeroutput"><span class="identifier">closed</span></code>), or the system time | |
3005 | reaches the passed time_point (return value <code class="computeroutput"><span class="identifier">timeout</span></code>). | |
3006 | </p></dd> | |
3007 | <dt><span class="term">Throws:</span></dt> | |
3008 | <dd><p> | |
3009 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
3010 | or exceptions thrown by memory allocation and copying or moving | |
3011 | <code class="computeroutput"><span class="identifier">va</span></code> or timeout-related | |
3012 | exceptions. | |
3013 | </p></dd> | |
3014 | </dl> | |
3015 | </div> | |
3016 | <p> | |
3017 | </p> | |
3018 | <h5> | |
3019 | <a name="bounded_channel_try_push_bridgehead"></a> | |
3020 | <span><a name="bounded_channel_try_push"></a></span> | |
3021 | <a class="link" href="pooled_fixedsize.html#bounded_channel_try_push">Member | |
3022 | function <code class="computeroutput">try_push</code>()</a> | |
3023 | </h5> | |
3024 | <p> | |
3025 | </p> | |
3026 | <pre class="programlisting"><span class="identifier">channel_op_status</span> <span class="identifier">try_push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
3027 | <span class="identifier">channel_op_status</span> <span class="identifier">try_push</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">);</span> | |
3028 | </pre> | |
3029 | <div class="variablelist"> | |
3030 | <p class="title"><b></b></p> | |
3031 | <dl> | |
3032 | <dt><span class="term">Effects:</span></dt> | |
3033 | <dd><p> | |
3034 | If channel is full, returns <code class="computeroutput"><span class="identifier">full</span></code>. | |
3035 | If channel is closed, returns <code class="computeroutput"><span class="identifier">closed</span></code>. | |
3036 | Otherwise enqueues the value in the channel, wakes up a fiber | |
3037 | blocked on <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span></code>, <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">pop_wait_until</span><span class="special">()</span></code> and returns <code class="computeroutput"><span class="identifier">success</span></code>. | |
3038 | </p></dd> | |
3039 | <dt><span class="term">Throws:</span></dt> | |
3040 | <dd><p> | |
3041 | Exceptions thrown by memory allocation and copying or moving | |
3042 | <code class="computeroutput"><span class="identifier">va</span></code>. | |
3043 | </p></dd> | |
3044 | </dl> | |
3045 | </div> | |
3046 | <p> | |
3047 | </p> | |
3048 | <h5> | |
3049 | <a name="bounded_channel_pop_bridgehead"></a> | |
3050 | <span><a name="bounded_channel_pop"></a></span> | |
3051 | <a class="link" href="pooled_fixedsize.html#bounded_channel_pop">Member | |
3052 | function <code class="computeroutput">pop</code>()</a> | |
3053 | </h5> | |
3054 | <p> | |
3055 | </p> | |
3056 | <pre class="programlisting"><span class="identifier">channel_op_status</span> <span class="identifier">pop</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
3057 | </pre> | |
3058 | <div class="variablelist"> | |
3059 | <p class="title"><b></b></p> | |
3060 | <dl> | |
3061 | <dt><span class="term">Effects:</span></dt> | |
3062 | <dd><p> | |
3063 | Dequeues a value from the channel. If the channel is empty, the | |
3064 | fiber gets suspended until at least one new item is <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>ed | |
3065 | (return value <code class="computeroutput"><span class="identifier">success</span></code> | |
3066 | and <code class="computeroutput"><span class="identifier">va</span></code> contains | |
3067 | dequeued value) or the channel gets <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (return value <code class="computeroutput"><span class="identifier">closed</span></code>). Once the number of | |
3068 | items remaining in the channel drops to <code class="computeroutput"><span class="identifier">lwm</span></code>, | |
3069 | any fibers blocked on <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">push_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">push_wait_until</span><span class="special">()</span></code> may resume. | |
3070 | </p></dd> | |
3071 | <dt><span class="term">Throws:</span></dt> | |
3072 | <dd><p> | |
3073 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
3074 | </p></dd> | |
3075 | </dl> | |
3076 | </div> | |
3077 | <p> | |
3078 | </p> | |
3079 | <h5> | |
3080 | <a name="bounded_channel_value_pop_bridgehead"></a> | |
3081 | <span><a name="bounded_channel_value_pop"></a></span> | |
3082 | <a class="link" href="pooled_fixedsize.html#bounded_channel_value_pop">Member | |
3083 | function <code class="computeroutput">value_pop</code>()</a> | |
3084 | </h5> | |
3085 | <p> | |
3086 | </p> | |
3087 | <pre class="programlisting"><span class="identifier">value_type</span> <span class="identifier">value_pop</span><span class="special">();</span> | |
3088 | </pre> | |
3089 | <div class="variablelist"> | |
3090 | <p class="title"><b></b></p> | |
3091 | <dl> | |
3092 | <dt><span class="term">Effects:</span></dt> | |
3093 | <dd><p> | |
3094 | Dequeues a value from the channel. If the channel is empty, the | |
3095 | fiber gets suspended until at least one new item is <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>ed | |
3096 | or the channel gets <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (which throws an exception). | |
3097 | Once the number of items remaining in the channel drops to <code class="computeroutput"><span class="identifier">lwm</span></code>, any fibers blocked on | |
3098 | <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>, | |
3099 | <code class="computeroutput"><span class="identifier">push_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">push_wait_until</span><span class="special">()</span></code> may resume. | |
3100 | </p></dd> | |
3101 | <dt><span class="term">Throws:</span></dt> | |
3102 | <dd><p> | |
3103 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> if | |
3104 | <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
3105 | is closed or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
3106 | </p></dd> | |
3107 | <dt><span class="term">Error conditions:</span></dt> | |
3108 | <dd><p> | |
3109 | <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">errc</span><span class="special">::</span><span class="identifier">operation_not_permitted</span></code> | |
3110 | </p></dd> | |
3111 | </dl> | |
3112 | </div> | |
3113 | <p> | |
3114 | </p> | |
3115 | <h5> | |
3116 | <a name="bounded_channel_try_pop_bridgehead"></a> | |
3117 | <span><a name="bounded_channel_try_pop"></a></span> | |
3118 | <a class="link" href="pooled_fixedsize.html#bounded_channel_try_pop">Member | |
3119 | function <code class="computeroutput">try_pop</code>()</a> | |
3120 | </h5> | |
3121 | <p> | |
3122 | </p> | |
3123 | <pre class="programlisting"><span class="identifier">channel_op_status</span> <span class="identifier">try_pop</span><span class="special">(</span> <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">);</span> | |
3124 | </pre> | |
3125 | <div class="variablelist"> | |
3126 | <p class="title"><b></b></p> | |
3127 | <dl> | |
3128 | <dt><span class="term">Effects:</span></dt> | |
3129 | <dd><p> | |
3130 | If channel is empty, returns <code class="computeroutput"><span class="identifier">empty</span></code>. | |
3131 | If channel is closed, returns <code class="computeroutput"><span class="identifier">closed</span></code>. | |
3132 | Otherwise it returns <code class="computeroutput"><span class="identifier">success</span></code> | |
3133 | and <code class="computeroutput"><span class="identifier">va</span></code> contains | |
3134 | the dequeued value. Once the number of items remaining in the | |
3135 | channel drops to <code class="computeroutput"><span class="identifier">lwm</span></code>, | |
3136 | any fibers blocked on <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">push_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">push_wait_until</span><span class="special">()</span></code> may resume. | |
3137 | </p></dd> | |
3138 | <dt><span class="term">Throws:</span></dt> | |
3139 | <dd><p> | |
3140 | Exceptions thrown by copy- or move-operations. | |
3141 | </p></dd> | |
3142 | </dl> | |
3143 | </div> | |
3144 | <p> | |
3145 | </p> | |
3146 | <h5> | |
3147 | <a name="bounded_channel_pop_wait_for_bridgehead"></a> | |
3148 | <span><a name="bounded_channel_pop_wait_for"></a></span> | |
3149 | <a class="link" href="pooled_fixedsize.html#bounded_channel_pop_wait_for">Member | |
3150 | function <code class="computeroutput">pop_wait_for</code>()</a> | |
3151 | </h5> | |
3152 | <p> | |
3153 | </p> | |
3154 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Period</span> <span class="special">></span> | |
3155 | <span class="identifier">channel_op_status</span> <span class="identifier">pop_wait_for</span><span class="special">(</span> | |
3156 | <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
3157 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">)</span> | |
3158 | </pre> | |
3159 | <div class="variablelist"> | |
3160 | <p class="title"><b></b></p> | |
3161 | <dl> | |
3162 | <dt><span class="term">Effects:</span></dt> | |
3163 | <dd><p> | |
3164 | Accepts <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span></code> and internally computes | |
3165 | a timeout time as (system time + <code class="computeroutput"><span class="identifier">timeout_duration</span></code>). | |
3166 | If channel is not empty, immediately dequeues a value from the | |
3167 | channel. Otherwise the fiber gets suspended until at least one | |
3168 | new item is <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>ed (return value <code class="computeroutput"><span class="identifier">success</span></code> and <code class="computeroutput"><span class="identifier">va</span></code> | |
3169 | contains dequeued value), or the channel gets <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (return value <code class="computeroutput"><span class="identifier">closed</span></code>), or the system time | |
3170 | reaches the computed timeout time (return value <code class="computeroutput"><span class="identifier">timeout</span></code>). Once the number of | |
3171 | items remaining in the channel drops to <code class="computeroutput"><span class="identifier">lwm</span></code>, | |
3172 | any fibers blocked on <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">push_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">push_wait_until</span><span class="special">()</span></code> may resume. | |
3173 | </p></dd> | |
3174 | <dt><span class="term">Throws:</span></dt> | |
3175 | <dd><p> | |
3176 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
3177 | or timeout-related exceptions. | |
3178 | </p></dd> | |
3179 | </dl> | |
3180 | </div> | |
3181 | <p> | |
3182 | </p> | |
3183 | <h5> | |
3184 | <a name="bounded_channel_pop_wait_until_bridgehead"></a> | |
3185 | <span><a name="bounded_channel_pop_wait_until"></a></span> | |
3186 | <a class="link" href="pooled_fixedsize.html#bounded_channel_pop_wait_until">Member | |
3187 | function <code class="computeroutput">pop_wait_until</code>()</a> | |
3188 | </h5> | |
3189 | <p> | |
3190 | </p> | |
3191 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
3192 | <span class="identifier">channel_op_status</span> <span class="identifier">pop_wait_until</span><span class="special">(</span> | |
3193 | <span class="identifier">value_type</span> <span class="special">&</span> <span class="identifier">va</span><span class="special">,</span> | |
3194 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">)</span> | |
3195 | </pre> | |
3196 | <div class="variablelist"> | |
3197 | <p class="title"><b></b></p> | |
3198 | <dl> | |
3199 | <dt><span class="term">Effects:</span></dt> | |
3200 | <dd><p> | |
3201 | Accepts a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> | |
3202 | <span class="special">></span></code>. If channel is not | |
3203 | empty, immediately dequeues a value from the channel. Otherwise | |
3204 | the fiber gets suspended until at least one new item is <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>ed | |
3205 | (return value <code class="computeroutput"><span class="identifier">success</span></code> | |
3206 | and <code class="computeroutput"><span class="identifier">va</span></code> contains | |
3207 | dequeued value), or the channel gets <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>d (return value <code class="computeroutput"><span class="identifier">closed</span></code>), or the system time | |
3208 | reaches the passed <code class="computeroutput"><span class="identifier">time_point</span></code> | |
3209 | (return value <code class="computeroutput"><span class="identifier">timeout</span></code>). | |
3210 | Once the number of items remaining in the channel drops to <code class="computeroutput"><span class="identifier">lwm</span></code>, any fibers blocked on | |
3211 | <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code>, | |
3212 | <code class="computeroutput"><span class="identifier">push_wait_for</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">push_wait_until</span><span class="special">()</span></code> may resume. | |
3213 | </p></dd> | |
3214 | <dt><span class="term">Throws:</span></dt> | |
3215 | <dd><p> | |
3216 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
3217 | or timeout-related exceptions. | |
3218 | </p></dd> | |
3219 | </dl> | |
3220 | </div> | |
3221 | </div> | |
3222 | <div class="section"> | |
3223 | <div class="titlepage"><div><div><h6 class="title"> | |
3224 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures" title="Futures">Futures</a> | |
3225 | </h6></div></div></div> | |
3226 | <div class="toc"><dl> | |
3227 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future">Future</a></span></dt> | |
3228 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise">Template | |
3229 | <code class="computeroutput"><span class="identifier">promise</span><span class="special"><></span></code></a></span></dt> | |
3230 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task">Template | |
3231 | <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code></a></span></dt> | |
3232 | </dl></div> | |
3233 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.h0"></a> | |
3234 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.overview"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.overview">Overview</a> | |
3235 | </h7><p> | |
3236 | The futures library provides a means of handling asynchronous future | |
3237 | values, whether those values are generated by another fiber, or on | |
3238 | a single fiber in response to external stimuli, or on-demand. | |
3239 | </p> | |
3240 | <p> | |
3241 | This is done through the provision of four class templates: <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> and | |
3242 | <a class="link" href="pooled_fixedsize.html#class_shared_future"> <code class="computeroutput">shared_future<></code></a> which are used to retrieve | |
3243 | the asynchronous results, and <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a> and <a class="link" href="pooled_fixedsize.html#class_packaged_task"> <code class="computeroutput">packaged_task<></code></a> which | |
3244 | are used to generate the asynchronous results. | |
3245 | </p> | |
3246 | <p> | |
3247 | An instance of <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> holds the one and only reference | |
3248 | to a result. Ownership can be transferred between instances using the | |
3249 | move constructor or move-assignment operator, but at most one instance | |
3250 | holds a reference to a given asynchronous result. When the result is | |
3251 | ready, it is returned from <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a> by rvalue-reference | |
3252 | to allow the result to be moved or copied as appropriate for the type. | |
3253 | </p> | |
3254 | <p> | |
3255 | On the other hand, many instances of <a class="link" href="pooled_fixedsize.html#class_shared_future"> <code class="computeroutput">shared_future<></code></a> may | |
3256 | reference the same result. Instances can be freely copied and assigned, | |
3257 | and <a class="link" href="pooled_fixedsize.html#shared_future_get"> <code class="computeroutput">shared_future::get()</code></a> | |
3258 | returns a <code class="computeroutput"><span class="keyword">const</span></code> | |
3259 | reference so that multiple calls to <a class="link" href="pooled_fixedsize.html#shared_future_get"> <code class="computeroutput">shared_future::get()</code></a> | |
3260 | are | |
3261 | safe. You can move an instance of <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> into an | |
3262 | instance of <a class="link" href="pooled_fixedsize.html#class_shared_future"> <code class="computeroutput">shared_future<></code></a>, thus transferring | |
3263 | ownership of the associated asynchronous result, but not vice-versa. | |
3264 | </p> | |
3265 | <p> | |
3266 | <a class="link" href="pooled_fixedsize.html#fibers_async"> <code class="computeroutput">fibers::async()</code></a> is a simple way of running asynchronous | |
3267 | tasks. A call to <code class="computeroutput"><span class="identifier">async</span><span class="special">()</span></code> spawns a fiber and returns a <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> that | |
3268 | will deliver the result of the fiber function. | |
3269 | </p> | |
3270 | <h7><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.h1"></a> | |
3271 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.creating_asynchronous_values"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.creating_asynchronous_values">Creating | |
3272 | asynchronous values</a> | |
3273 | </h7><p> | |
3274 | You can set the value in a future with either a <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a> or | |
3275 | a <a class="link" href="pooled_fixedsize.html#class_packaged_task"> <code class="computeroutput">packaged_task<></code></a>. A <a class="link" href="pooled_fixedsize.html#class_packaged_task"> <code class="computeroutput">packaged_task<></code></a> is | |
3276 | a callable object with <code class="computeroutput"><span class="keyword">void</span></code> | |
3277 | return that wraps a function or callable object returning the specified | |
3278 | type. When the <a class="link" href="pooled_fixedsize.html#class_packaged_task"> <code class="computeroutput">packaged_task<></code></a> is invoked, | |
3279 | it invokes the contained function in turn, and populates a future with | |
3280 | the contained function's return value. This is an answer to the perennial | |
3281 | question: <span class="quote">“<span class="quote">How do I return a value from a fiber?</span>”</span> Package | |
3282 | the function you wish to run as a <a class="link" href="pooled_fixedsize.html#class_packaged_task"> <code class="computeroutput">packaged_task<></code></a> and | |
3283 | pass the packaged task to the fiber constructor. The future retrieved | |
3284 | from the packaged task can then be used to obtain the return value. | |
3285 | If the function throws an exception, that is stored in the future in | |
3286 | place of the return value. | |
3287 | </p> | |
3288 | <pre class="programlisting"><span class="keyword">int</span> <span class="identifier">calculate_the_answer_to_life_the_universe_and_everything</span><span class="special">()</span> <span class="special">{</span> | |
3289 | <span class="keyword">return</span> <span class="number">42</span><span class="special">;</span> | |
3290 | <span class="special">}</span> | |
3291 | ||
3292 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">packaged_task</span><span class="special"><</span><span class="keyword">int</span><span class="special">()></span> <span class="identifier">pt</span><span class="special">(</span><span class="identifier">calculate_the_answer_to_life_the_universe_and_everything</span><span class="special">);</span> | |
3293 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">fi</span><span class="special">=</span><span class="identifier">pt</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">();</span> | |
3294 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">pt</span><span class="special">)).</span><span class="identifier">detach</span><span class="special">();</span> <span class="comment">// launch task on a fiber</span> | |
3295 | ||
3296 | <span class="identifier">fi</span><span class="special">.</span><span class="identifier">wait</span><span class="special">();</span> <span class="comment">// wait for it to finish</span> | |
3297 | ||
3298 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">is_ready</span><span class="special">());</span> | |
3299 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">has_value</span><span class="special">());</span> | |
3300 | <span class="identifier">assert</span><span class="special">(!</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">has_exception</span><span class="special">());</span> | |
3301 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">get</span><span class="special">()==</span><span class="number">42</span><span class="special">);</span> | |
3302 | </pre> | |
3303 | <p> | |
3304 | A <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a> is a bit more low level: it just provides | |
3305 | explicit functions to store a value or an exception in the associated | |
3306 | future. A promise can therefore be used where the value might come | |
3307 | from more than one possible source. | |
3308 | </p> | |
3309 | <pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">promise</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">pi</span><span class="special">;</span> | |
3310 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">fi</span><span class="special">;</span> | |
3311 | <span class="identifier">fi</span><span class="special">=</span><span class="identifier">pi</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">();</span> | |
3312 | ||
3313 | <span class="identifier">pi</span><span class="special">.</span><span class="identifier">set_value</span><span class="special">(</span><span class="number">42</span><span class="special">);</span> | |
3314 | ||
3315 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">is_ready</span><span class="special">());</span> | |
3316 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">has_value</span><span class="special">());</span> | |
3317 | <span class="identifier">assert</span><span class="special">(!</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">has_exception</span><span class="special">());</span> | |
3318 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">fi</span><span class="special">.</span><span class="identifier">get</span><span class="special">()==</span><span class="number">42</span><span class="special">);</span> | |
3319 | </pre> | |
3320 | <div class="section"> | |
3321 | <div class="titlepage"><div><div><h6 class="title"> | |
3322 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future" title="Future">Future</a> | |
3323 | </h6></div></div></div> | |
3324 | <p> | |
3325 | A future provides a mechanism to access the result of an asynchronous | |
3326 | operation. | |
3327 | </p> | |
3328 | <a name="shared_state"></a><h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h0"></a> | |
3329 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.shared_state"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.shared_state">shared | |
3330 | state</a> | |
3331 | </h8><p> | |
3332 | Behind a <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a> and its <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> lies | |
3333 | an unspecified object called their <span class="emphasis"><em>shared state</em></span>. | |
3334 | The shared state is what will actually hold the async result (or | |
3335 | the exception). | |
3336 | </p> | |
3337 | <p> | |
3338 | The shared state is instantiated along with the <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a>. | |
3339 | </p> | |
3340 | <p> | |
3341 | Aside from its originating <code class="computeroutput"><span class="identifier">promise</span><span class="special"><></span></code>, a <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> holds | |
3342 | a unique reference to a particular shared state. However, multiple | |
3343 | <a class="link" href="pooled_fixedsize.html#class_shared_future"> <code class="computeroutput">shared_future<></code></a> instances can reference the | |
3344 | same underlying shared state. | |
3345 | </p> | |
3346 | <p> | |
3347 | As <a class="link" href="pooled_fixedsize.html#class_packaged_task"> <code class="computeroutput">packaged_task<></code></a> and <a class="link" href="pooled_fixedsize.html#fibers_async"> <code class="computeroutput">fibers::async()</code></a> are | |
3348 | implemented using <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a>, discussions of shared | |
3349 | state apply to them as well. | |
3350 | </p> | |
3351 | <a name="class_future_status"></a><h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h1"></a> | |
3352 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.enumeration__code__phrase_role__identifier__future_status__phrase___code_">Enumeration | |
3353 | <code class="computeroutput"><span class="identifier">future_status</span></code></a> | |
3354 | </h8><p> | |
3355 | Timed wait-operations ( <a class="link" href="pooled_fixedsize.html#future_wait_for"> <code class="computeroutput">future::wait_for()</code></a> and <a class="link" href="pooled_fixedsize.html#future_wait_until"> <code class="computeroutput">future::wait_until()</code></a>) | |
3356 | return the state of the future. | |
3357 | </p> | |
3358 | <pre class="programlisting"><span class="keyword">enum</span> <span class="keyword">class</span> <span class="identifier">future_status</span> <span class="special">{</span> | |
3359 | <span class="identifier">ready</span><span class="special">,</span> | |
3360 | <span class="identifier">timeout</span><span class="special">,</span> | |
3361 | <span class="identifier">deferred</span> <span class="comment">// not supported yet</span> | |
3362 | <span class="special">};</span> | |
3363 | </pre> | |
3364 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h2"></a> | |
3365 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future._code__phrase_role__identifier__ready__phrase___code_"><code class="computeroutput"><span class="identifier">ready</span></code></a> | |
3366 | </h8><div class="variablelist"> | |
3367 | <p class="title"><b></b></p> | |
3368 | <dl> | |
3369 | <dt><span class="term">Effects:</span></dt> | |
3370 | <dd><p> | |
3371 | The <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> is ready. | |
3372 | </p></dd> | |
3373 | </dl> | |
3374 | </div> | |
3375 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h3"></a> | |
3376 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future._code__phrase_role__identifier__timeout__phrase___code_"><code class="computeroutput"><span class="identifier">timeout</span></code></a> | |
3377 | </h8><div class="variablelist"> | |
3378 | <p class="title"><b></b></p> | |
3379 | <dl> | |
3380 | <dt><span class="term">Effects:</span></dt> | |
3381 | <dd><p> | |
3382 | The <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> did not | |
3383 | become ready before timeout has passed. | |
3384 | </p></dd> | |
3385 | </dl> | |
3386 | </div> | |
3387 | <div class="note"><table border="0" summary="Note"> | |
3388 | <tr> | |
3389 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> | |
3390 | <th align="left">Note</th> | |
3391 | </tr> | |
3392 | <tr><td align="left" valign="top"><p> | |
3393 | Deferred futures are not supported. | |
3394 | </p></td></tr> | |
3395 | </table></div> | |
3396 | <p> | |
3397 | </p> | |
3398 | <h5> | |
3399 | <a name="class_future_bridgehead"></a> | |
3400 | <span><a name="class_future"></a></span> | |
3401 | <a class="link" href="pooled_fixedsize.html#class_future">Template <code class="computeroutput">future<></code></a> | |
3402 | </h5> | |
3403 | <p> | |
3404 | </p> | |
3405 | <p> | |
3406 | A <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> contains a <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
3407 | state</a> which is not shared with any other future. | |
3408 | </p> | |
3409 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">R</span> <span class="special">></span> | |
3410 | <span class="keyword">class</span> <span class="identifier">future</span> <span class="special">{</span> | |
3411 | <span class="keyword">public</span><span class="special">:</span> | |
3412 | <span class="identifier">future</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3413 | ||
3414 | <span class="identifier">future</span><span class="special">(</span> <span class="identifier">future</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
3415 | ||
3416 | <span class="identifier">future</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">future</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
3417 | ||
3418 | <span class="identifier">future</span><span class="special">(</span> <span class="identifier">future</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3419 | ||
3420 | <span class="identifier">future</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">future</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3421 | ||
3422 | <span class="special">~</span><span class="identifier">future</span><span class="special">();</span> | |
3423 | ||
3424 | <span class="keyword">bool</span> <span class="identifier">valid</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3425 | ||
3426 | <span class="identifier">shared_future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="identifier">share</span><span class="special">();</span> | |
3427 | ||
3428 | <span class="identifier">R</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of generic future template</span> | |
3429 | <span class="identifier">R</span> <span class="special">&</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of future< R & > template specialization</span> | |
3430 | <span class="keyword">void</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of future< void > template specialization</span> | |
3431 | ||
3432 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">get_exception_ptr</span><span class="special">();</span> | |
3433 | ||
3434 | <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span> | |
3435 | ||
3436 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Period</span> <span class="special">></span> | |
3437 | <span class="identifier">future_status</span> <span class="identifier">wait_for</span><span class="special">(</span> | |
3438 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span> | |
3439 | ||
3440 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
3441 | <span class="identifier">future_status</span> <span class="identifier">wait_until</span><span class="special">(</span> | |
3442 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span> | |
3443 | <span class="special">};</span> | |
3444 | </pre> | |
3445 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h4"></a> | |
3446 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.default_constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.default_constructor">Default | |
3447 | constructor</a> | |
3448 | </h8><pre class="programlisting"><span class="identifier">future</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3449 | </pre> | |
3450 | <div class="variablelist"> | |
3451 | <p class="title"><b></b></p> | |
3452 | <dl> | |
3453 | <dt><span class="term">Effects:</span></dt> | |
3454 | <dd><p> | |
3455 | Creates a future with no <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
3456 | state</a>. After construction <code class="computeroutput"><span class="keyword">false</span> | |
3457 | <span class="special">==</span> <span class="identifier">valid</span><span class="special">()</span></code>. | |
3458 | </p></dd> | |
3459 | <dt><span class="term">Throws:</span></dt> | |
3460 | <dd><p> | |
3461 | Nothing. | |
3462 | </p></dd> | |
3463 | </dl> | |
3464 | </div> | |
3465 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h5"></a> | |
3466 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.move_constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.move_constructor">Move | |
3467 | constructor</a> | |
3468 | </h8><pre class="programlisting"><span class="identifier">future</span><span class="special">(</span> <span class="identifier">future</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3469 | </pre> | |
3470 | <div class="variablelist"> | |
3471 | <p class="title"><b></b></p> | |
3472 | <dl> | |
3473 | <dt><span class="term">Effects:</span></dt> | |
3474 | <dd><p> | |
3475 | Constructs a future with the <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
3476 | state</a> of other. After construction <code class="computeroutput"><span class="keyword">false</span> | |
3477 | <span class="special">==</span> <span class="identifier">other</span><span class="special">.</span><span class="identifier">valid</span><span class="special">()</span></code>. | |
3478 | </p></dd> | |
3479 | <dt><span class="term">Throws:</span></dt> | |
3480 | <dd><p> | |
3481 | Nothing. | |
3482 | </p></dd> | |
3483 | </dl> | |
3484 | </div> | |
3485 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h6"></a> | |
3486 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.destructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.destructor">Destructor</a> | |
3487 | </h8><pre class="programlisting"><span class="special">~</span><span class="identifier">future</span><span class="special">();</span> | |
3488 | </pre> | |
3489 | <div class="variablelist"> | |
3490 | <p class="title"><b></b></p> | |
3491 | <dl> | |
3492 | <dt><span class="term">Effects:</span></dt> | |
3493 | <dd><p> | |
3494 | Destroys the future; ownership is abandoned. | |
3495 | </p></dd> | |
3496 | <dt><span class="term">Note:</span></dt> | |
3497 | <dd><p> | |
3498 | <code class="computeroutput">~future()</code> does <span class="emphasis"><em>not</em></span> block the calling fiber. | |
3499 | </p></dd> | |
3500 | </dl> | |
3501 | </div> | |
3502 | <p> | |
3503 | Consider a sequence such as: | |
3504 | </p> | |
3505 | <div class="orderedlist"><ol class="orderedlist" type="1"> | |
3506 | <li class="listitem"> | |
3507 | instantiate <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a> | |
3508 | </li> | |
3509 | <li class="listitem"> | |
3510 | obtain its <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> via <a class="link" href="pooled_fixedsize.html#promise_get_future"> <code class="computeroutput">promise::get_future()</code></a> | |
3511 | </li> | |
3512 | <li class="listitem"> | |
3513 | launch <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a>, capturing <code class="computeroutput"><span class="identifier">promise</span><span class="special"><></span></code> | |
3514 | </li> | |
3515 | <li class="listitem"> | |
3516 | destroy <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> | |
3517 | </li> | |
3518 | <li class="listitem"> | |
3519 | call <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> | |
3520 | </li> | |
3521 | </ol></div> | |
3522 | <p> | |
3523 | The final <code class="computeroutput"><span class="identifier">set_value</span><span class="special">()</span></code> call succeeds, but the value is | |
3524 | silently discarded: no additional <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> can be obtained from that | |
3525 | <code class="computeroutput"><span class="identifier">promise</span><span class="special"><></span></code>. | |
3526 | </p> | |
3527 | <p> | |
3528 | </p> | |
3529 | <h5> | |
3530 | <a name="future_operator_assign_bridgehead"></a> | |
3531 | <span><a name="future_operator_assign"></a></span> | |
3532 | <a class="link" href="pooled_fixedsize.html#future_operator_assign">Member | |
3533 | function <code class="computeroutput">operator=</code>()</a> | |
3534 | </h5> | |
3535 | <p> | |
3536 | </p> | |
3537 | <pre class="programlisting"><span class="identifier">future</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">future</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3538 | </pre> | |
3539 | <div class="variablelist"> | |
3540 | <p class="title"><b></b></p> | |
3541 | <dl> | |
3542 | <dt><span class="term">Effects:</span></dt> | |
3543 | <dd><p> | |
3544 | Moves the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> | |
3545 | of other to <code class="computeroutput"><span class="keyword">this</span></code>. | |
3546 | After the assignment, <code class="computeroutput"><span class="keyword">false</span> | |
3547 | <span class="special">==</span> <span class="identifier">other</span><span class="special">.</span><span class="identifier">valid</span><span class="special">()</span></code>. | |
3548 | </p></dd> | |
3549 | <dt><span class="term">Throws:</span></dt> | |
3550 | <dd><p> | |
3551 | Nothing. | |
3552 | </p></dd> | |
3553 | </dl> | |
3554 | </div> | |
3555 | <p> | |
3556 | </p> | |
3557 | <h5> | |
3558 | <a name="future_valid_bridgehead"></a> | |
3559 | <span><a name="future_valid"></a></span> | |
3560 | <a class="link" href="pooled_fixedsize.html#future_valid">Member function <code class="computeroutput">valid</code>()</a> | |
3561 | </h5> | |
3562 | <p> | |
3563 | </p> | |
3564 | <pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">valid</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3565 | </pre> | |
3566 | <div class="variablelist"> | |
3567 | <p class="title"><b></b></p> | |
3568 | <dl> | |
3569 | <dt><span class="term">Effects:</span></dt> | |
3570 | <dd><p> | |
3571 | Returns <code class="computeroutput"><span class="keyword">true</span></code> if | |
3572 | future contains a <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a>. | |
3573 | </p></dd> | |
3574 | <dt><span class="term">Throws:</span></dt> | |
3575 | <dd><p> | |
3576 | Nothing. | |
3577 | </p></dd> | |
3578 | </dl> | |
3579 | </div> | |
3580 | <p> | |
3581 | </p> | |
3582 | <h5> | |
3583 | <a name="future_share_bridgehead"></a> | |
3584 | <span><a name="future_share"></a></span> | |
3585 | <a class="link" href="pooled_fixedsize.html#future_share">Member function <code class="computeroutput">share</code>()</a> | |
3586 | </h5> | |
3587 | <p> | |
3588 | </p> | |
3589 | <pre class="programlisting"><span class="identifier">shared_future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="identifier">share</span><span class="special">();</span> | |
3590 | </pre> | |
3591 | <div class="variablelist"> | |
3592 | <p class="title"><b></b></p> | |
3593 | <dl> | |
3594 | <dt><span class="term">Effects:</span></dt> | |
3595 | <dd><p> | |
3596 | Move the state to a <a class="link" href="pooled_fixedsize.html#class_shared_future"> <code class="computeroutput">shared_future<></code></a>. | |
3597 | </p></dd> | |
3598 | <dt><span class="term">Returns:</span></dt> | |
3599 | <dd><p> | |
3600 | a <a class="link" href="pooled_fixedsize.html#class_shared_future"> <code class="computeroutput">shared_future<></code></a> containing the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> formerly belonging | |
3601 | to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. | |
3602 | </p></dd> | |
3603 | <dt><span class="term">Postcondition:</span></dt> | |
3604 | <dd><p> | |
3605 | <code class="computeroutput"><span class="keyword">false</span> <span class="special">==</span> | |
3606 | <span class="identifier">valid</span><span class="special">()</span></code> | |
3607 | </p></dd> | |
3608 | <dt><span class="term">Throws:</span></dt> | |
3609 | <dd><p> | |
3610 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
3611 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code>. | |
3612 | </p></dd> | |
3613 | </dl> | |
3614 | </div> | |
3615 | <p> | |
3616 | </p> | |
3617 | <h5> | |
3618 | <a name="future_get_bridgehead"></a> | |
3619 | <span><a name="future_get"></a></span> | |
3620 | <a class="link" href="pooled_fixedsize.html#future_get">Member function <code class="computeroutput">get</code>()</a> | |
3621 | </h5> | |
3622 | <p> | |
3623 | </p> | |
3624 | <pre class="programlisting"><span class="identifier">R</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of generic future template</span> | |
3625 | <span class="identifier">R</span> <span class="special">&</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of future< R & > template specialization</span> | |
3626 | <span class="keyword">void</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of future< void > template specialization</span> | |
3627 | </pre> | |
3628 | <div class="variablelist"> | |
3629 | <p class="title"><b></b></p> | |
3630 | <dl> | |
3631 | <dt><span class="term">Precondition:</span></dt> | |
3632 | <dd><p> | |
3633 | <code class="computeroutput"><span class="keyword">true</span> <span class="special">==</span> | |
3634 | <span class="identifier">valid</span><span class="special">()</span></code> | |
3635 | </p></dd> | |
3636 | <dt><span class="term">Returns:</span></dt> | |
3637 | <dd><p> | |
3638 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
3639 | called. If <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> is called, | |
3640 | returns the value. If <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
3641 | called, throws the indicated exception. | |
3642 | </p></dd> | |
3643 | <dt><span class="term">Postcondition:</span></dt> | |
3644 | <dd><p> | |
3645 | <code class="computeroutput"><span class="keyword">false</span> <span class="special">==</span> | |
3646 | <span class="identifier">valid</span><span class="special">()</span></code> | |
3647 | </p></dd> | |
3648 | <dt><span class="term">Throws:</span></dt> | |
3649 | <dd><p> | |
3650 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
3651 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code>, | |
3652 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code>, | |
3653 | <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">broken_promise</span></code>. | |
3654 | Any exception passed to <code class="computeroutput"><span class="identifier">promise</span><span class="special">::</span><span class="identifier">set_exception</span><span class="special">()</span></code>. | |
3655 | </p></dd> | |
3656 | </dl> | |
3657 | </div> | |
3658 | <p> | |
3659 | </p> | |
3660 | <h5> | |
3661 | <a name="future_get_exception_ptr_bridgehead"></a> | |
3662 | <span><a name="future_get_exception_ptr"></a></span> | |
3663 | <a class="link" href="pooled_fixedsize.html#future_get_exception_ptr">Member | |
3664 | function <code class="computeroutput">get_exception_ptr</code>()</a> | |
3665 | </h5> | |
3666 | <p> | |
3667 | </p> | |
3668 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">get_exception_ptr</span><span class="special">();</span> | |
3669 | </pre> | |
3670 | <div class="variablelist"> | |
3671 | <p class="title"><b></b></p> | |
3672 | <dl> | |
3673 | <dt><span class="term">Precondition:</span></dt> | |
3674 | <dd><p> | |
3675 | <code class="computeroutput"><span class="keyword">true</span> <span class="special">==</span> | |
3676 | <span class="identifier">valid</span><span class="special">()</span></code> | |
3677 | </p></dd> | |
3678 | <dt><span class="term">Returns:</span></dt> | |
3679 | <dd><p> | |
3680 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
3681 | called. If <code class="computeroutput"><span class="identifier">set_value</span><span class="special">()</span></code> is called, returns a default-constructed | |
3682 | <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>. If <code class="computeroutput"><span class="identifier">set_exception</span><span class="special">()</span></code> | |
3683 | is called, returns the passed <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>. | |
3684 | </p></dd> | |
3685 | <dt><span class="term">Throws:</span></dt> | |
3686 | <dd><p> | |
3687 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
3688 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code> | |
3689 | or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code>. | |
3690 | </p></dd> | |
3691 | <dt><span class="term">Note:</span></dt> | |
3692 | <dd><p> | |
3693 | <code class="computeroutput"><span class="identifier">get_exception_ptr</span><span class="special">()</span></code> does <span class="emphasis"><em>not</em></span> | |
3694 | invalidate the <code class="computeroutput">future</code>. After calling <code class="computeroutput"><span class="identifier">get_exception_ptr</span><span class="special">()</span></code>, you may still call <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a>. | |
3695 | </p></dd> | |
3696 | </dl> | |
3697 | </div> | |
3698 | <p> | |
3699 | </p> | |
3700 | <h5> | |
3701 | <a name="future_wait_bridgehead"></a> | |
3702 | <span><a name="future_wait"></a></span> | |
3703 | <a class="link" href="pooled_fixedsize.html#future_wait">Member function <code class="computeroutput">wait</code>()</a> | |
3704 | </h5> | |
3705 | <p> | |
3706 | </p> | |
3707 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">wait</span><span class="special">();</span> | |
3708 | </pre> | |
3709 | <div class="variablelist"> | |
3710 | <p class="title"><b></b></p> | |
3711 | <dl> | |
3712 | <dt><span class="term">Effects:</span></dt> | |
3713 | <dd><p> | |
3714 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
3715 | called. | |
3716 | </p></dd> | |
3717 | <dt><span class="term">Throws:</span></dt> | |
3718 | <dd><p> | |
3719 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
3720 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code> | |
3721 | or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code>. | |
3722 | </p></dd> | |
3723 | </dl> | |
3724 | </div> | |
3725 | <p> | |
3726 | </p> | |
3727 | <h5> | |
3728 | <a name="future_wait_for_bridgehead"></a> | |
3729 | <span><a name="future_wait_for"></a></span> | |
3730 | <a class="link" href="pooled_fixedsize.html#future_wait_for">Templated | |
3731 | member function <code class="computeroutput">wait_for</code>()</a> | |
3732 | </h5> | |
3733 | <p> | |
3734 | </p> | |
3735 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Period</span> <span class="special">></span> | |
3736 | <span class="identifier">future_status</span> <span class="identifier">wait_for</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span> | |
3737 | </pre> | |
3738 | <div class="variablelist"> | |
3739 | <p class="title"><b></b></p> | |
3740 | <dl> | |
3741 | <dt><span class="term">Effects:</span></dt> | |
3742 | <dd><p> | |
3743 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
3744 | called, or <code class="computeroutput"><span class="identifier">timeout_duration</span></code> | |
3745 | has passed. | |
3746 | </p></dd> | |
3747 | <dt><span class="term">Result:</span></dt> | |
3748 | <dd><p> | |
3749 | A <code class="computeroutput"><span class="identifier">future_status</span></code> | |
3750 | is returned indicating the reason for returning. | |
3751 | </p></dd> | |
3752 | <dt><span class="term">Throws:</span></dt> | |
3753 | <dd><p> | |
3754 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
3755 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code> | |
3756 | or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
3757 | or timeout-related exceptions. | |
3758 | </p></dd> | |
3759 | </dl> | |
3760 | </div> | |
3761 | <p> | |
3762 | </p> | |
3763 | <h5> | |
3764 | <a name="future_wait_until_bridgehead"></a> | |
3765 | <span><a name="future_wait_until"></a></span> | |
3766 | <a class="link" href="pooled_fixedsize.html#future_wait_until">Templated | |
3767 | member function <code class="computeroutput">wait_until</code>()</a> | |
3768 | </h5> | |
3769 | <p> | |
3770 | </p> | |
3771 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
3772 | <span class="identifier">future_status</span> <span class="identifier">wait_until</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span> | |
3773 | </pre> | |
3774 | <div class="variablelist"> | |
3775 | <p class="title"><b></b></p> | |
3776 | <dl> | |
3777 | <dt><span class="term">Effects:</span></dt> | |
3778 | <dd><p> | |
3779 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
3780 | called, or <code class="computeroutput"><span class="identifier">timeout_time</span></code> | |
3781 | has passed. | |
3782 | </p></dd> | |
3783 | <dt><span class="term">Result:</span></dt> | |
3784 | <dd><p> | |
3785 | A <code class="computeroutput"><span class="identifier">future_status</span></code> | |
3786 | is returned indicating the reason for returning. | |
3787 | </p></dd> | |
3788 | <dt><span class="term">Throws:</span></dt> | |
3789 | <dd><p> | |
3790 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
3791 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code> | |
3792 | or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
3793 | or timeout-related exceptions. | |
3794 | </p></dd> | |
3795 | </dl> | |
3796 | </div> | |
3797 | <p> | |
3798 | </p> | |
3799 | <h5> | |
3800 | <a name="class_shared_future_bridgehead"></a> | |
3801 | <span><a name="class_shared_future"></a></span> | |
3802 | <a class="link" href="pooled_fixedsize.html#class_shared_future">Template | |
3803 | <code class="computeroutput">shared_future<></code></a> | |
3804 | </h5> | |
3805 | <p> | |
3806 | </p> | |
3807 | <p> | |
3808 | A <a class="link" href="pooled_fixedsize.html#class_shared_future"> <code class="computeroutput">shared_future<></code></a> contains a <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
3809 | state</a> which might be shared with other <a class="link" href="pooled_fixedsize.html#class_shared_future"> <code class="computeroutput">shared_future<></code></a> instances. | |
3810 | </p> | |
3811 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">R</span> <span class="special">></span> | |
3812 | <span class="keyword">class</span> <span class="identifier">shared_future</span> <span class="special">{</span> | |
3813 | <span class="keyword">public</span><span class="special">:</span> | |
3814 | <span class="identifier">shared_future</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3815 | ||
3816 | <span class="special">~</span><span class="identifier">shared_future</span><span class="special">();</span> | |
3817 | ||
3818 | <span class="identifier">shared_future</span><span class="special">(</span> <span class="identifier">shared_future</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">);</span> | |
3819 | ||
3820 | <span class="identifier">shared_future</span><span class="special">(</span> <span class="identifier">future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3821 | ||
3822 | <span class="identifier">shared_future</span><span class="special">(</span> <span class="identifier">shared_future</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3823 | ||
3824 | <span class="identifier">shared_future</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">shared_future</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3825 | ||
3826 | <span class="identifier">shared_future</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3827 | ||
3828 | <span class="identifier">shared_future</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">shared_future</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3829 | ||
3830 | <span class="keyword">bool</span> <span class="identifier">valid</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3831 | ||
3832 | <span class="identifier">R</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of generic shared_future template</span> | |
3833 | <span class="identifier">R</span> <span class="special">&</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of shared_future< R & > template specialization</span> | |
3834 | <span class="keyword">void</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of shared_future< void > template specialization</span> | |
3835 | ||
3836 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">get_exception_ptr</span><span class="special">();</span> | |
3837 | ||
3838 | <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span> | |
3839 | ||
3840 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Period</span> <span class="special">></span> | |
3841 | <span class="identifier">future_status</span> <span class="identifier">wait_for</span><span class="special">(</span> | |
3842 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span> | |
3843 | ||
3844 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
3845 | <span class="identifier">future_status</span> <span class="identifier">wait_until</span><span class="special">(</span> | |
3846 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span> | |
3847 | <span class="special">};</span> | |
3848 | </pre> | |
3849 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h7"></a> | |
3850 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.default_constructor0"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.default_constructor0">Default | |
3851 | constructor</a> | |
3852 | </h8><pre class="programlisting"><span class="identifier">shared_future</span><span class="special">();</span> | |
3853 | </pre> | |
3854 | <div class="variablelist"> | |
3855 | <p class="title"><b></b></p> | |
3856 | <dl> | |
3857 | <dt><span class="term">Effects:</span></dt> | |
3858 | <dd><p> | |
3859 | Creates a shared_future with no <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
3860 | state</a>. After construction <code class="computeroutput"><span class="keyword">false</span> | |
3861 | <span class="special">==</span> <span class="identifier">valid</span><span class="special">()</span></code>. | |
3862 | </p></dd> | |
3863 | <dt><span class="term">Throws:</span></dt> | |
3864 | <dd><p> | |
3865 | Nothing. | |
3866 | </p></dd> | |
3867 | </dl> | |
3868 | </div> | |
3869 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h8"></a> | |
3870 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.move_constructor0"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.move_constructor0">Move | |
3871 | constructor</a> | |
3872 | </h8><pre class="programlisting"><span class="identifier">shared_future</span><span class="special">(</span> <span class="identifier">future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3873 | <span class="identifier">shared_future</span><span class="special">(</span> <span class="identifier">shared_future</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3874 | </pre> | |
3875 | <div class="variablelist"> | |
3876 | <p class="title"><b></b></p> | |
3877 | <dl> | |
3878 | <dt><span class="term">Effects:</span></dt> | |
3879 | <dd><p> | |
3880 | Constructs a shared_future with the <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
3881 | state</a> of other. After construction <code class="computeroutput"><span class="keyword">false</span> | |
3882 | <span class="special">==</span> <span class="identifier">other</span><span class="special">.</span><span class="identifier">valid</span><span class="special">()</span></code>. | |
3883 | </p></dd> | |
3884 | <dt><span class="term">Throws:</span></dt> | |
3885 | <dd><p> | |
3886 | Nothing. | |
3887 | </p></dd> | |
3888 | </dl> | |
3889 | </div> | |
3890 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h9"></a> | |
3891 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.copy_constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.copy_constructor">Copy | |
3892 | constructor</a> | |
3893 | </h8><pre class="programlisting"><span class="identifier">shared_future</span><span class="special">(</span> <span class="identifier">shared_future</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3894 | </pre> | |
3895 | <div class="variablelist"> | |
3896 | <p class="title"><b></b></p> | |
3897 | <dl> | |
3898 | <dt><span class="term">Effects:</span></dt> | |
3899 | <dd><p> | |
3900 | Constructs a shared_future with the <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
3901 | state</a> of other. After construction <code class="computeroutput"><span class="identifier">other</span><span class="special">.</span><span class="identifier">valid</span><span class="special">()</span></code> is unchanged. | |
3902 | </p></dd> | |
3903 | <dt><span class="term">Throws:</span></dt> | |
3904 | <dd><p> | |
3905 | Nothing. | |
3906 | </p></dd> | |
3907 | </dl> | |
3908 | </div> | |
3909 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.h10"></a> | |
3910 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.destructor0"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.future.destructor0">Destructor</a> | |
3911 | </h8><pre class="programlisting"><span class="special">~</span><span class="identifier">shared_future</span><span class="special">();</span> | |
3912 | </pre> | |
3913 | <div class="variablelist"> | |
3914 | <p class="title"><b></b></p> | |
3915 | <dl> | |
3916 | <dt><span class="term">Effects:</span></dt> | |
3917 | <dd><p> | |
3918 | Destroys the shared_future; ownership is abandoned if not shared. | |
3919 | </p></dd> | |
3920 | <dt><span class="term">Note:</span></dt> | |
3921 | <dd><p> | |
3922 | <code class="computeroutput">~shared_future()</code> does <span class="emphasis"><em>not</em></span> block the calling | |
3923 | fiber. | |
3924 | </p></dd> | |
3925 | </dl> | |
3926 | </div> | |
3927 | <p> | |
3928 | </p> | |
3929 | <h5> | |
3930 | <a name="shared_future_operator_assign_bridgehead"></a> | |
3931 | <span><a name="shared_future_operator_assign"></a></span> | |
3932 | <a class="link" href="pooled_fixedsize.html#shared_future_operator_assign">Member | |
3933 | function <code class="computeroutput">operator=</code>()</a> | |
3934 | </h5> | |
3935 | <p> | |
3936 | </p> | |
3937 | <pre class="programlisting"><span class="identifier">shared_future</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3938 | <span class="identifier">shared_future</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">shared_future</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3939 | <span class="identifier">shared_future</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">shared_future</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3940 | </pre> | |
3941 | <div class="variablelist"> | |
3942 | <p class="title"><b></b></p> | |
3943 | <dl> | |
3944 | <dt><span class="term">Effects:</span></dt> | |
3945 | <dd><p> | |
3946 | Moves or copies the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> | |
3947 | of other to <code class="computeroutput"><span class="keyword">this</span></code>. | |
3948 | After the assignment, the state of <code class="computeroutput"><span class="identifier">other</span><span class="special">.</span><span class="identifier">valid</span><span class="special">()</span></code> depends on which overload | |
3949 | was invoked: unchanged for the overload accepting <code class="computeroutput"><span class="identifier">shared_future</span> <span class="keyword">const</span><span class="special">&</span></code>, otherwise <code class="computeroutput"><span class="keyword">false</span></code>. | |
3950 | </p></dd> | |
3951 | <dt><span class="term">Throws:</span></dt> | |
3952 | <dd><p> | |
3953 | Nothing. | |
3954 | </p></dd> | |
3955 | </dl> | |
3956 | </div> | |
3957 | <p> | |
3958 | </p> | |
3959 | <h5> | |
3960 | <a name="shared_future_valid_bridgehead"></a> | |
3961 | <span><a name="shared_future_valid"></a></span> | |
3962 | <a class="link" href="pooled_fixedsize.html#shared_future_valid">Member | |
3963 | function <code class="computeroutput">valid</code>()</a> | |
3964 | </h5> | |
3965 | <p> | |
3966 | </p> | |
3967 | <pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">valid</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
3968 | </pre> | |
3969 | <div class="variablelist"> | |
3970 | <p class="title"><b></b></p> | |
3971 | <dl> | |
3972 | <dt><span class="term">Effects:</span></dt> | |
3973 | <dd><p> | |
3974 | Returns <code class="computeroutput"><span class="keyword">true</span></code> if | |
3975 | shared_future contains a <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
3976 | state</a>. | |
3977 | </p></dd> | |
3978 | <dt><span class="term">Throws:</span></dt> | |
3979 | <dd><p> | |
3980 | Nothing. | |
3981 | </p></dd> | |
3982 | </dl> | |
3983 | </div> | |
3984 | <p> | |
3985 | </p> | |
3986 | <h5> | |
3987 | <a name="shared_future_get_bridgehead"></a> | |
3988 | <span><a name="shared_future_get"></a></span> | |
3989 | <a class="link" href="pooled_fixedsize.html#shared_future_get">Member | |
3990 | function <code class="computeroutput">get</code>()</a> | |
3991 | </h5> | |
3992 | <p> | |
3993 | </p> | |
3994 | <pre class="programlisting"><span class="identifier">R</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of generic shared_future template</span> | |
3995 | <span class="identifier">R</span> <span class="special">&</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of shared_future< R & > template specialization</span> | |
3996 | <span class="keyword">void</span> <span class="identifier">get</span><span class="special">();</span> <span class="comment">// member only of shared_future< void > template specialization</span> | |
3997 | </pre> | |
3998 | <div class="variablelist"> | |
3999 | <p class="title"><b></b></p> | |
4000 | <dl> | |
4001 | <dt><span class="term">Precondition:</span></dt> | |
4002 | <dd><p> | |
4003 | <code class="computeroutput"><span class="keyword">true</span> <span class="special">==</span> | |
4004 | <span class="identifier">valid</span><span class="special">()</span></code> | |
4005 | </p></dd> | |
4006 | <dt><span class="term">Returns:</span></dt> | |
4007 | <dd><p> | |
4008 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
4009 | called. If <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> is called, | |
4010 | returns the value. If <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
4011 | called, throws the indicated exception. | |
4012 | </p></dd> | |
4013 | <dt><span class="term">Postcondition:</span></dt> | |
4014 | <dd><p> | |
4015 | <code class="computeroutput"><span class="keyword">false</span> <span class="special">==</span> | |
4016 | <span class="identifier">valid</span><span class="special">()</span></code> | |
4017 | </p></dd> | |
4018 | <dt><span class="term">Throws:</span></dt> | |
4019 | <dd><p> | |
4020 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4021 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code>, | |
4022 | <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code>, | |
4023 | <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">broken_promise</span></code>. | |
4024 | Any exception passed to <code class="computeroutput"><span class="identifier">promise</span><span class="special">::</span><span class="identifier">set_exception</span><span class="special">()</span></code>. | |
4025 | </p></dd> | |
4026 | </dl> | |
4027 | </div> | |
4028 | <p> | |
4029 | </p> | |
4030 | <h5> | |
4031 | <a name="shared_future_get_exception_ptr_bridgehead"></a> | |
4032 | <span><a name="shared_future_get_exception_ptr"></a></span> | |
4033 | <a class="link" href="pooled_fixedsize.html#shared_future_get_exception_ptr">Member | |
4034 | function <code class="computeroutput">get_exception_ptr</code>()</a> | |
4035 | </h5> | |
4036 | <p> | |
4037 | </p> | |
4038 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">get_exception_ptr</span><span class="special">();</span> | |
4039 | </pre> | |
4040 | <div class="variablelist"> | |
4041 | <p class="title"><b></b></p> | |
4042 | <dl> | |
4043 | <dt><span class="term">Precondition:</span></dt> | |
4044 | <dd><p> | |
4045 | <code class="computeroutput"><span class="keyword">true</span> <span class="special">==</span> | |
4046 | <span class="identifier">valid</span><span class="special">()</span></code> | |
4047 | </p></dd> | |
4048 | <dt><span class="term">Returns:</span></dt> | |
4049 | <dd><p> | |
4050 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
4051 | called. If <code class="computeroutput"><span class="identifier">set_value</span><span class="special">()</span></code> is called, returns a default-constructed | |
4052 | <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>. If <code class="computeroutput"><span class="identifier">set_exception</span><span class="special">()</span></code> | |
4053 | is called, returns the passed <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>. | |
4054 | </p></dd> | |
4055 | <dt><span class="term">Throws:</span></dt> | |
4056 | <dd><p> | |
4057 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4058 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code> | |
4059 | or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code>. | |
4060 | </p></dd> | |
4061 | <dt><span class="term">Note:</span></dt> | |
4062 | <dd><p> | |
4063 | <code class="computeroutput"><span class="identifier">get_exception_ptr</span><span class="special">()</span></code> does <span class="emphasis"><em>not</em></span> | |
4064 | invalidate the <code class="computeroutput">shared_future</code>. After calling <code class="computeroutput"><span class="identifier">get_exception_ptr</span><span class="special">()</span></code>, you may still call <a class="link" href="pooled_fixedsize.html#shared_future_get"> <code class="computeroutput">shared_future::get()</code></a>. | |
4065 | </p></dd> | |
4066 | </dl> | |
4067 | </div> | |
4068 | <p> | |
4069 | </p> | |
4070 | <h5> | |
4071 | <a name="shared_future_wait_bridgehead"></a> | |
4072 | <span><a name="shared_future_wait"></a></span> | |
4073 | <a class="link" href="pooled_fixedsize.html#shared_future_wait">Member | |
4074 | function <code class="computeroutput">wait</code>()</a> | |
4075 | </h5> | |
4076 | <p> | |
4077 | </p> | |
4078 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">wait</span><span class="special">();</span> | |
4079 | </pre> | |
4080 | <div class="variablelist"> | |
4081 | <p class="title"><b></b></p> | |
4082 | <dl> | |
4083 | <dt><span class="term">Effects:</span></dt> | |
4084 | <dd><p> | |
4085 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
4086 | called. | |
4087 | </p></dd> | |
4088 | <dt><span class="term">Throws:</span></dt> | |
4089 | <dd><p> | |
4090 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4091 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code> | |
4092 | or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code>. | |
4093 | </p></dd> | |
4094 | </dl> | |
4095 | </div> | |
4096 | <p> | |
4097 | </p> | |
4098 | <h5> | |
4099 | <a name="shared_future_wait_for_bridgehead"></a> | |
4100 | <span><a name="shared_future_wait_for"></a></span> | |
4101 | <a class="link" href="pooled_fixedsize.html#shared_future_wait_for">Templated | |
4102 | member function <code class="computeroutput">wait_for</code>()</a> | |
4103 | </h5> | |
4104 | <p> | |
4105 | </p> | |
4106 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Period</span> <span class="special">></span> | |
4107 | <span class="identifier">future_status</span> <span class="identifier">wait_for</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">duration</span><span class="special"><</span> <span class="identifier">Rep</span><span class="special">,</span> <span class="identifier">Period</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_duration</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span> | |
4108 | </pre> | |
4109 | <div class="variablelist"> | |
4110 | <p class="title"><b></b></p> | |
4111 | <dl> | |
4112 | <dt><span class="term">Effects:</span></dt> | |
4113 | <dd><p> | |
4114 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
4115 | called, or <code class="computeroutput"><span class="identifier">timeout_duration</span></code> | |
4116 | has passed. | |
4117 | </p></dd> | |
4118 | <dt><span class="term">Result:</span></dt> | |
4119 | <dd><p> | |
4120 | A <code class="computeroutput"><span class="identifier">future_status</span></code> | |
4121 | is returned indicating the reason for returning. | |
4122 | </p></dd> | |
4123 | <dt><span class="term">Throws:</span></dt> | |
4124 | <dd><p> | |
4125 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4126 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code> | |
4127 | or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
4128 | or timeout-related exceptions. | |
4129 | </p></dd> | |
4130 | </dl> | |
4131 | </div> | |
4132 | <p> | |
4133 | </p> | |
4134 | <h5> | |
4135 | <a name="shared_future_wait_until_bridgehead"></a> | |
4136 | <span><a name="shared_future_wait_until"></a></span> | |
4137 | <a class="link" href="pooled_fixedsize.html#shared_future_wait_until">Templated | |
4138 | member function <code class="computeroutput">wait_until</code>()</a> | |
4139 | </h5> | |
4140 | <p> | |
4141 | </p> | |
4142 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Duration</span> <span class="special">></span> | |
4143 | <span class="identifier">future_status</span> <span class="identifier">wait_until</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">time_point</span><span class="special"><</span> <span class="identifier">Clock</span><span class="special">,</span> <span class="identifier">Duration</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">timeout_time</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span> | |
4144 | </pre> | |
4145 | <div class="variablelist"> | |
4146 | <p class="title"><b></b></p> | |
4147 | <dl> | |
4148 | <dt><span class="term">Effects:</span></dt> | |
4149 | <dd><p> | |
4150 | Waits until <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> or <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a> is | |
4151 | called, or <code class="computeroutput"><span class="identifier">timeout_time</span></code> | |
4152 | has passed. | |
4153 | </p></dd> | |
4154 | <dt><span class="term">Result:</span></dt> | |
4155 | <dd><p> | |
4156 | A <code class="computeroutput"><span class="identifier">future_status</span></code> | |
4157 | is returned indicating the reason for returning. | |
4158 | </p></dd> | |
4159 | <dt><span class="term">Throws:</span></dt> | |
4160 | <dd><p> | |
4161 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4162 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code> | |
4163 | or <code class="computeroutput"><span class="identifier">fiber_interrupted</span></code> | |
4164 | or timeout-related exceptions. | |
4165 | </p></dd> | |
4166 | </dl> | |
4167 | </div> | |
4168 | <p> | |
4169 | </p> | |
4170 | <h5> | |
4171 | <a name="fibers_async_bridgehead"></a> | |
4172 | <span><a name="fibers_async"></a></span> | |
4173 | <a class="link" href="pooled_fixedsize.html#fibers_async">Non-member function | |
4174 | <code class="computeroutput">fibers::async()</code></a> | |
4175 | </h5> | |
4176 | <p> | |
4177 | </p> | |
4178 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">future</span><span class="special">/</span><span class="identifier">async</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
4179 | ||
4180 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">Function</span><span class="special">,</span> <span class="keyword">class</span> <span class="special">...</span> <span class="identifier">Args</span> <span class="special">></span> | |
4181 | <span class="identifier">future</span><span class="special"><</span> | |
4182 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of_t</span><span class="special"><</span> | |
4183 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay_t</span><span class="special"><</span> <span class="identifier">Function</span> <span class="special">>(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay_t</span><span class="special"><</span> <span class="identifier">Args</span> <span class="special">></span> <span class="special">...</span> <span class="special">)</span> | |
4184 | <span class="special">></span> | |
4185 | <span class="special">></span> | |
4186 | <span class="identifier">async</span><span class="special">(</span> <span class="identifier">Function</span> <span class="special">&&</span> <span class="identifier">fn</span><span class="special">,</span> <span class="identifier">Args</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">args</span><span class="special">);</span> | |
4187 | ||
4188 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <a class="link" href="../../stack.html#stack_allocator_concept"><code class="computeroutput"><span class="identifier">StackAllocator</span></code></a><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Function</span><span class="special">,</span> <span class="keyword">class</span> <span class="special">...</span> <span class="identifier">Args</span> <span class="special">></span> | |
4189 | <span class="identifier">future</span><span class="special"><</span> | |
4190 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of_t</span><span class="special"><</span> | |
4191 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay_t</span><span class="special"><</span> <span class="identifier">Function</span> <span class="special">>(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay_t</span><span class="special"><</span> <span class="identifier">Args</span> <span class="special">></span> <span class="special">...</span> <span class="special">)</span> | |
4192 | <span class="special">></span> | |
4193 | <span class="special">></span> | |
4194 | <span class="identifier">async</span><span class="special">(</span> <a href="http://en.cppreference.com/w/cpp/memory/allocator_arg_t" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator_arg_t</span></code></a><span class="special">,</span> <a class="link" href="../../stack.html#stack_allocator_concept"><code class="computeroutput"><span class="identifier">StackAllocator</span></code></a> <span class="identifier">salloc</span><span class="special">,</span> <span class="identifier">Function</span> <span class="special">&&</span> <span class="identifier">fn</span><span class="special">,</span> <span class="identifier">Args</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">args</span><span class="special">);</span> | |
4195 | </pre> | |
4196 | <div class="variablelist"> | |
4197 | <p class="title"><b></b></p> | |
4198 | <dl> | |
4199 | <dt><span class="term">Effects:</span></dt> | |
4200 | <dd><p> | |
4201 | Executes <code class="computeroutput"><span class="identifier">fn</span></code> | |
4202 | in a <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> and returns an associated <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a>. | |
4203 | </p></dd> | |
4204 | <dt><span class="term">Result:</span></dt> | |
4205 | <dd> | |
4206 | <p> | |
4207 | </p> | |
4208 | <pre class="programlisting"><span class="identifier">future</span><span class="special"><</span> | |
4209 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of_t</span><span class="special"><</span> | |
4210 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay_t</span><span class="special"><</span> <span class="identifier">Function</span> <span class="special">>(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay_t</span><span class="special"><</span> <span class="identifier">Args</span> <span class="special">></span> <span class="special">...</span> <span class="special">)</span> | |
4211 | <span class="special">></span> | |
4212 | <span class="special">></span></pre> | |
4213 | <p> | |
4214 | representing the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> | |
4215 | associated with the asynchronous execution of <code class="computeroutput"><span class="identifier">fn</span></code>. | |
4216 | </p> | |
4217 | </dd> | |
4218 | <dt><span class="term">Throws:</span></dt> | |
4219 | <dd><p> | |
4220 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> | |
4221 | or <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4222 | if an error occurs. | |
4223 | </p></dd> | |
4224 | <dt><span class="term">Notes:</span></dt> | |
4225 | <dd><p> | |
4226 | The overload accepting <a href="http://en.cppreference.com/w/cpp/memory/allocator_arg_t" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator_arg_t</span></code></a> uses | |
4227 | the passed <a class="link" href="../../stack.html#stack_allocator_concept"><code class="computeroutput"><span class="identifier">StackAllocator</span></code></a> when | |
4228 | constructing the launched <code class="computeroutput"><span class="identifier">fiber</span></code>. | |
4229 | </p></dd> | |
4230 | </dl> | |
4231 | </div> | |
4232 | <div class="note"><table border="0" summary="Note"> | |
4233 | <tr> | |
4234 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> | |
4235 | <th align="left">Note</th> | |
4236 | </tr> | |
4237 | <tr><td align="left" valign="top"><p> | |
4238 | Deferred futures are not supported. | |
4239 | </p></td></tr> | |
4240 | </table></div> | |
4241 | </div> | |
4242 | <div class="section"> | |
4243 | <div class="titlepage"><div><div><h6 class="title"> | |
4244 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise"></a><a name="class_promise"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise" title="Template promise<>">Template | |
4245 | <code class="computeroutput"><span class="identifier">promise</span><span class="special"><></span></code></a> | |
4246 | </h6></div></div></div> | |
4247 | <p> | |
4248 | A <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a> provides a mechanism to store a value | |
4249 | (or exception) that can later be retrieved from the corresponding | |
4250 | <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> object. <code class="computeroutput"><span class="identifier">promise</span><span class="special"><></span></code> and <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> communicate via their underlying | |
4251 | <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a>. | |
4252 | </p> | |
4253 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">R</span> <span class="special">></span> | |
4254 | <span class="keyword">class</span> <span class="identifier">promise</span> <span class="special">{</span> | |
4255 | <span class="keyword">public</span><span class="special">:</span> | |
4256 | <span class="identifier">promise</span><span class="special">();</span> | |
4257 | ||
4258 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="special">></span> | |
4259 | <span class="identifier">promise</span><span class="special">(</span> <a href="http://en.cppreference.com/w/cpp/memory/allocator_arg_t" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator_arg_t</span></code></a><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">);</span> | |
4260 | ||
4261 | <span class="identifier">promise</span><span class="special">(</span> <span class="identifier">promise</span> <span class="special">&&)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4262 | ||
4263 | <span class="identifier">promise</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">promise</span> <span class="special">&&)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4264 | ||
4265 | <span class="identifier">promise</span><span class="special">(</span> <span class="identifier">promise</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
4266 | ||
4267 | <span class="identifier">promise</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">promise</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
4268 | ||
4269 | <span class="special">~</span><span class="identifier">promise</span><span class="special">();</span> | |
4270 | ||
4271 | <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">promise</span> <span class="special">&)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4272 | ||
4273 | <span class="identifier">future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="identifier">get_future</span><span class="special">();</span> | |
4274 | ||
4275 | <span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">R</span> <span class="keyword">const</span><span class="special">&);</span> <span class="comment">// member only of generic promise template</span> | |
4276 | <span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">R</span> <span class="special">&&);</span> <span class="comment">// member only of generic promise template</span> | |
4277 | <span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">R</span> <span class="special">&);</span> <span class="comment">// member only of promise< R & > template</span> | |
4278 | <span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">();</span> <span class="comment">// member only of promise< void > template</span> | |
4279 | ||
4280 | <span class="keyword">void</span> <span class="identifier">set_exception</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">p</span><span class="special">);</span> | |
4281 | <span class="special">};</span> | |
4282 | ||
4283 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">R</span> <span class="special">></span> | |
4284 | <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">promise</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="special">&,</span> <span class="identifier">promise</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="special">&)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4285 | </pre> | |
4286 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.h0"></a> | |
4287 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.default_constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.default_constructor">Default | |
4288 | constructor</a> | |
4289 | </h8><pre class="programlisting"><span class="identifier">promise</span><span class="special">();</span> | |
4290 | </pre> | |
4291 | <div class="variablelist"> | |
4292 | <p class="title"><b></b></p> | |
4293 | <dl> | |
4294 | <dt><span class="term">Effects:</span></dt> | |
4295 | <dd><p> | |
4296 | Creates a promise with an empty <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4297 | state</a>. | |
4298 | </p></dd> | |
4299 | <dt><span class="term">Throws:</span></dt> | |
4300 | <dd><p> | |
4301 | Exceptions caused by memory allocation. | |
4302 | </p></dd> | |
4303 | </dl> | |
4304 | </div> | |
4305 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.h1"></a> | |
4306 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.constructor">Constructor</a> | |
4307 | </h8><pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="special">></span> | |
4308 | <span class="identifier">promise</span><span class="special">(</span> <a href="http://en.cppreference.com/w/cpp/memory/allocator_arg_t" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator_arg_t</span></code></a><span class="special">,</span> <span class="identifier">Allocator</span> <span class="identifier">alloc</span><span class="special">);</span> | |
4309 | </pre> | |
4310 | <div class="variablelist"> | |
4311 | <p class="title"><b></b></p> | |
4312 | <dl> | |
4313 | <dt><span class="term">Effects:</span></dt> | |
4314 | <dd><p> | |
4315 | Creates a promise with an empty <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4316 | state</a> by using <code class="computeroutput"><span class="identifier">alloc</span></code>. | |
4317 | </p></dd> | |
4318 | <dt><span class="term">Throws:</span></dt> | |
4319 | <dd><p> | |
4320 | Exceptions caused by memory allocation. | |
4321 | </p></dd> | |
4322 | <dt><span class="term">See also:</span></dt> | |
4323 | <dd><p> | |
4324 | <a href="http://en.cppreference.com/w/cpp/memory/allocator_arg_t" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator_arg_t</span></code></a> | |
4325 | </p></dd> | |
4326 | </dl> | |
4327 | </div> | |
4328 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.h2"></a> | |
4329 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.move_constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.move_constructor">Move | |
4330 | constructor</a> | |
4331 | </h8><pre class="programlisting"><span class="identifier">promise</span><span class="special">(</span> <span class="identifier">promise</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4332 | </pre> | |
4333 | <div class="variablelist"> | |
4334 | <p class="title"><b></b></p> | |
4335 | <dl> | |
4336 | <dt><span class="term">Effects:</span></dt> | |
4337 | <dd><p> | |
4338 | Creates a promise by moving the <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4339 | state</a> from <code class="computeroutput"><span class="identifier">other</span></code>. | |
4340 | </p></dd> | |
4341 | <dt><span class="term">Postcondition:</span></dt> | |
4342 | <dd><p> | |
4343 | <code class="computeroutput"><span class="identifier">other</span></code> contains | |
4344 | no valid shared state. | |
4345 | </p></dd> | |
4346 | <dt><span class="term">Throws:</span></dt> | |
4347 | <dd><p> | |
4348 | Nothing. | |
4349 | </p></dd> | |
4350 | </dl> | |
4351 | </div> | |
4352 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.h3"></a> | |
4353 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.destructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.promise.destructor">Destructor</a> | |
4354 | </h8><pre class="programlisting"><span class="special">~</span><span class="identifier">promise</span><span class="special">();</span> | |
4355 | </pre> | |
4356 | <div class="variablelist"> | |
4357 | <p class="title"><b></b></p> | |
4358 | <dl> | |
4359 | <dt><span class="term">Effects:</span></dt> | |
4360 | <dd><p> | |
4361 | Destroys <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
4362 | and abandons the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> | |
4363 | if shared state is ready; otherwise stores <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4364 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">broken_promise</span></code> | |
4365 | as if by <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a>: the | |
4366 | shared state is set ready. | |
4367 | </p></dd> | |
4368 | </dl> | |
4369 | </div> | |
4370 | <p> | |
4371 | </p> | |
4372 | <h5> | |
4373 | <a name="promise_operator_assign_bridgehead"></a> | |
4374 | <span><a name="promise_operator_assign"></a></span> | |
4375 | <a class="link" href="pooled_fixedsize.html#promise_operator_assign">Member | |
4376 | function <code class="computeroutput">operator=</code>()</a> | |
4377 | </h5> | |
4378 | <p> | |
4379 | </p> | |
4380 | <pre class="programlisting"><span class="identifier">promise</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">promise</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4381 | </pre> | |
4382 | <div class="variablelist"> | |
4383 | <p class="title"><b></b></p> | |
4384 | <dl> | |
4385 | <dt><span class="term">Effects:</span></dt> | |
4386 | <dd><p> | |
4387 | Transfers the ownership of <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4388 | state</a> to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. | |
4389 | </p></dd> | |
4390 | <dt><span class="term">Postcondition:</span></dt> | |
4391 | <dd><p> | |
4392 | <code class="computeroutput"><span class="identifier">other</span></code> contains | |
4393 | no valid shared state. | |
4394 | </p></dd> | |
4395 | <dt><span class="term">Throws:</span></dt> | |
4396 | <dd><p> | |
4397 | Nothing. | |
4398 | </p></dd> | |
4399 | </dl> | |
4400 | </div> | |
4401 | <p> | |
4402 | </p> | |
4403 | <h5> | |
4404 | <a name="promise_swap_bridgehead"></a> | |
4405 | <span><a name="promise_swap"></a></span> | |
4406 | <a class="link" href="pooled_fixedsize.html#promise_swap">Member function <code class="computeroutput">swap</code>()</a> | |
4407 | </h5> | |
4408 | <p> | |
4409 | </p> | |
4410 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">promise</span> <span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4411 | </pre> | |
4412 | <div class="variablelist"> | |
4413 | <p class="title"><b></b></p> | |
4414 | <dl> | |
4415 | <dt><span class="term">Effects:</span></dt> | |
4416 | <dd><p> | |
4417 | Swaps the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> | |
4418 | between other and <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. | |
4419 | </p></dd> | |
4420 | <dt><span class="term">Throws:</span></dt> | |
4421 | <dd><p> | |
4422 | Nothing. | |
4423 | </p></dd> | |
4424 | </dl> | |
4425 | </div> | |
4426 | <p> | |
4427 | </p> | |
4428 | <h5> | |
4429 | <a name="promise_get_future_bridgehead"></a> | |
4430 | <span><a name="promise_get_future"></a></span> | |
4431 | <a class="link" href="pooled_fixedsize.html#promise_get_future">Member | |
4432 | function <code class="computeroutput">get_future</code>()</a> | |
4433 | </h5> | |
4434 | <p> | |
4435 | </p> | |
4436 | <pre class="programlisting"><span class="identifier">future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="identifier">get_future</span><span class="special">();</span> | |
4437 | </pre> | |
4438 | <div class="variablelist"> | |
4439 | <p class="title"><b></b></p> | |
4440 | <dl> | |
4441 | <dt><span class="term">Returns:</span></dt> | |
4442 | <dd><p> | |
4443 | A <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> with the same <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4444 | state</a>. | |
4445 | </p></dd> | |
4446 | <dt><span class="term">Throws:</span></dt> | |
4447 | <dd><p> | |
4448 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4449 | with <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">future_already_retrieved</span></code> | |
4450 | or <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code>. | |
4451 | </p></dd> | |
4452 | </dl> | |
4453 | </div> | |
4454 | <p> | |
4455 | </p> | |
4456 | <h5> | |
4457 | <a name="promise_set_value_bridgehead"></a> | |
4458 | <span><a name="promise_set_value"></a></span> | |
4459 | <a class="link" href="pooled_fixedsize.html#promise_set_value">Member | |
4460 | function <code class="computeroutput">set_value</code>()</a> | |
4461 | </h5> | |
4462 | <p> | |
4463 | </p> | |
4464 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">R</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">value</span><span class="special">);</span> <span class="comment">// member only of generic promise template</span> | |
4465 | <span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">R</span> <span class="special">&&</span> <span class="identifier">value</span><span class="special">);</span> <span class="comment">// member only of generic promise template</span> | |
4466 | <span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">R</span> <span class="special">&</span> <span class="identifier">value</span><span class="special">);</span> <span class="comment">// member only of promise< R & > template</span> | |
4467 | <span class="keyword">void</span> <span class="identifier">set_value</span><span class="special">();</span> <span class="comment">// member only of promise< void > template</span> | |
4468 | </pre> | |
4469 | <div class="variablelist"> | |
4470 | <p class="title"><b></b></p> | |
4471 | <dl> | |
4472 | <dt><span class="term">Effects:</span></dt> | |
4473 | <dd><p> | |
4474 | Store the result in the <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4475 | state</a> and marks the state as ready. | |
4476 | </p></dd> | |
4477 | <dt><span class="term">Throws:</span></dt> | |
4478 | <dd><p> | |
4479 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4480 | with <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">future_already_satisfied</span></code> | |
4481 | or <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code>. | |
4482 | </p></dd> | |
4483 | </dl> | |
4484 | </div> | |
4485 | <p> | |
4486 | </p> | |
4487 | <h5> | |
4488 | <a name="promise_set_exception_bridgehead"></a> | |
4489 | <span><a name="promise_set_exception"></a></span> | |
4490 | <a class="link" href="pooled_fixedsize.html#promise_set_exception">Member | |
4491 | function <code class="computeroutput">set_exception</code>()</a> | |
4492 | </h5> | |
4493 | <p> | |
4494 | </p> | |
4495 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">set_exception</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span><span class="special">);</span> | |
4496 | </pre> | |
4497 | <div class="variablelist"> | |
4498 | <p class="title"><b></b></p> | |
4499 | <dl> | |
4500 | <dt><span class="term">Effects:</span></dt> | |
4501 | <dd><p> | |
4502 | Store an exception pointer in the <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4503 | state</a> and marks the state as ready. | |
4504 | </p></dd> | |
4505 | <dt><span class="term">Throws:</span></dt> | |
4506 | <dd><p> | |
4507 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4508 | with <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">future_already_satisfied</span></code> | |
4509 | or <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code>. | |
4510 | </p></dd> | |
4511 | </dl> | |
4512 | </div> | |
4513 | <p> | |
4514 | </p> | |
4515 | <h5> | |
4516 | <a name="swap_for_promise_bridgehead"></a> | |
4517 | <span><a name="swap_for_promise"></a></span> | |
4518 | <a class="link" href="pooled_fixedsize.html#swap_for_promise">Non-member | |
4519 | function <code class="computeroutput">swap()</code></a> | |
4520 | </h5> | |
4521 | <p> | |
4522 | </p> | |
4523 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">R</span> <span class="special">></span> | |
4524 | <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">promise</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="special">&</span> <span class="identifier">l</span><span class="special">,</span> <span class="identifier">promise</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="special">&</span> <span class="identifier">r</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4525 | </pre> | |
4526 | <div class="variablelist"> | |
4527 | <p class="title"><b></b></p> | |
4528 | <dl> | |
4529 | <dt><span class="term">Effects:</span></dt> | |
4530 | <dd><p> | |
4531 | Same as <code class="computeroutput"><span class="identifier">l</span><span class="special">.</span><span class="identifier">swap</span><span class="special">(</span> | |
4532 | <span class="identifier">r</span><span class="special">)</span></code>. | |
4533 | </p></dd> | |
4534 | </dl> | |
4535 | </div> | |
4536 | </div> | |
4537 | <div class="section"> | |
4538 | <div class="titlepage"><div><div><h6 class="title"> | |
4539 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task"></a><a name="class_packaged_task"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task" title="Template packaged_task<>">Template | |
4540 | <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code></a> | |
4541 | </h6></div></div></div> | |
4542 | <p> | |
4543 | A <a class="link" href="pooled_fixedsize.html#class_packaged_task"> <code class="computeroutput">packaged_task<></code></a> wraps a callable target | |
4544 | that returns a value so that the return value can be computed asynchronously. | |
4545 | </p> | |
4546 | <p> | |
4547 | Conventional usage of <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code> is like this: | |
4548 | </p> | |
4549 | <div class="orderedlist"><ol class="orderedlist" type="1"> | |
4550 | <li class="listitem"> | |
4551 | Instantiate <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code> with template arguments | |
4552 | matching the signature of the callable. Pass the callable to | |
4553 | the <a class="link" href="pooled_fixedsize.html#packaged_task_packaged_task">constructor</a>. | |
4554 | </li> | |
4555 | <li class="listitem"> | |
4556 | Call <a class="link" href="pooled_fixedsize.html#packaged_task_get_future"> <code class="computeroutput">packaged_task::get_future()</code></a> and capture | |
4557 | the returned <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> instance. | |
4558 | </li> | |
4559 | <li class="listitem"> | |
4560 | Launch a <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> to run the new <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code>, passing any arguments | |
4561 | required by the original callable. | |
4562 | </li> | |
4563 | <li class="listitem"> | |
4564 | Call <a class="link" href="../../fiber_mgmt/fiber.html#fiber_detach"> <code class="computeroutput">fiber::detach()</code></a> on the newly-launched <code class="computeroutput"><span class="identifier">fiber</span></code>. | |
4565 | </li> | |
4566 | <li class="listitem"> | |
4567 | At some later point, retrieve the result from the <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code>. | |
4568 | </li> | |
4569 | </ol></div> | |
4570 | <p> | |
4571 | This is, in fact, pretty much what <a class="link" href="pooled_fixedsize.html#fibers_async"> <code class="computeroutput">fibers::async()</code></a> | |
4572 | encapsulates. | |
4573 | </p> | |
4574 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">R</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Args</span> <span class="special">></span> | |
4575 | <span class="keyword">class</span> <span class="identifier">packaged_task</span><span class="special"><</span> <span class="identifier">R</span><span class="special">(</span> <span class="identifier">Args</span> <span class="special">...</span> <span class="special">)</span> <span class="special">></span> <span class="special">{</span> | |
4576 | <span class="keyword">public</span><span class="special">:</span> | |
4577 | <span class="identifier">packaged_task</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4578 | ||
4579 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span> <span class="special">></span> | |
4580 | <span class="keyword">explicit</span> <span class="identifier">packaged_task</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&);</span> | |
4581 | ||
4582 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="special">></span> | |
4583 | <span class="identifier">packaged_task</span><span class="special">(</span> <a href="http://en.cppreference.com/w/cpp/memory/allocator_arg_t" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator_arg_t</span></code></a><span class="special">,</span> <span class="identifier">Allocator</span> <span class="keyword">const</span><span class="special">&,</span> <span class="identifier">Fn</span> <span class="special">&&);</span> | |
4584 | ||
4585 | <span class="identifier">packaged_task</span><span class="special">(</span> <span class="identifier">packaged_task</span> <span class="special">&&)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4586 | ||
4587 | <span class="identifier">packaged_task</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">packaged_task</span> <span class="special">&&)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4588 | ||
4589 | <span class="identifier">packaged_task</span><span class="special">(</span> <span class="identifier">packaged_task</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
4590 | ||
4591 | <span class="identifier">packaged_task</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">packaged_task</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
4592 | ||
4593 | <span class="special">~</span><span class="identifier">packaged_task</span><span class="special">();</span> | |
4594 | ||
4595 | <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">packaged_task</span> <span class="special">&)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4596 | ||
4597 | <span class="keyword">bool</span> <span class="identifier">valid</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4598 | ||
4599 | <span class="identifier">future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="identifier">get_future</span><span class="special">();</span> | |
4600 | ||
4601 | <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span> <span class="identifier">Args</span> <span class="special">...);</span> | |
4602 | ||
4603 | <span class="keyword">void</span> <span class="identifier">reset</span><span class="special">();</span> | |
4604 | <span class="special">};</span> | |
4605 | ||
4606 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Signature</span> <span class="special">></span> | |
4607 | <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">packaged_task</span><span class="special"><</span> <span class="identifier">Signature</span> <span class="special">></span> <span class="special">&,</span> <span class="identifier">packaged_task</span><span class="special"><</span> <span class="identifier">Signature</span> <span class="special">></span> <span class="special">&)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4608 | </pre> | |
4609 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.h0"></a> | |
4610 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.default_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Default | |
4611 | constructor <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special">()</span></code></a> | |
4612 | </h8><pre class="programlisting"><span class="identifier">packaged_task</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4613 | </pre> | |
4614 | <div class="variablelist"> | |
4615 | <p class="title"><b></b></p> | |
4616 | <dl> | |
4617 | <dt><span class="term">Effects:</span></dt> | |
4618 | <dd><p> | |
4619 | Constructs an object of class <code class="computeroutput"><span class="identifier">packaged_task</span></code> | |
4620 | with no <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a>. | |
4621 | </p></dd> | |
4622 | <dt><span class="term">Throws:</span></dt> | |
4623 | <dd><p> | |
4624 | Nothing. | |
4625 | </p></dd> | |
4626 | </dl> | |
4627 | </div> | |
4628 | <a name="packaged_task_packaged_task"></a><h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.h1"></a> | |
4629 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.templated_constructor__code__phrase_role__identifier__packaged_task__phrase__phrase_role__special______phrase___code_">Templated | |
4630 | constructor <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special">()</span></code></a> | |
4631 | </h8><pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span> <span class="special">></span> | |
4632 | <span class="keyword">explicit</span> <span class="identifier">packaged_task</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">fn</span><span class="special">);</span> | |
4633 | ||
4634 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <a href="http://en.cppreference.com/w/cpp/concept/Allocator" target="_top"><code class="computeroutput"><span class="identifier">Allocator</span></code></a> <span class="special">></span> | |
4635 | <span class="identifier">packaged_task</span><span class="special">(</span> <a href="http://en.cppreference.com/w/cpp/memory/allocator_arg_t" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator_arg_t</span></code></a><span class="special">,</span> <span class="identifier">Allocator</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">alloc</span><span class="special">,</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">fn</span><span class="special">);</span> | |
4636 | </pre> | |
4637 | <div class="variablelist"> | |
4638 | <p class="title"><b></b></p> | |
4639 | <dl> | |
4640 | <dt><span class="term">Effects:</span></dt> | |
4641 | <dd><p> | |
4642 | Constructs an object of class <code class="computeroutput"><span class="identifier">packaged_task</span></code> | |
4643 | with a <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> and | |
4644 | copies or moves the callable target <code class="computeroutput"><span class="identifier">fn</span></code> | |
4645 | to internal storage. | |
4646 | </p></dd> | |
4647 | <dt><span class="term">Throws:</span></dt> | |
4648 | <dd><p> | |
4649 | Exceptions caused by memory allocation. | |
4650 | </p></dd> | |
4651 | <dt><span class="term">Note:</span></dt> | |
4652 | <dd><p> | |
4653 | The signature of <code class="computeroutput"><span class="identifier">Fn</span></code> | |
4654 | should have a return type convertible to <code class="computeroutput"><span class="identifier">R</span></code>. | |
4655 | </p></dd> | |
4656 | <dt><span class="term">See also:</span></dt> | |
4657 | <dd><p> | |
4658 | <a href="http://en.cppreference.com/w/cpp/memory/allocator_arg_t" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator_arg_t</span></code></a> | |
4659 | </p></dd> | |
4660 | </dl> | |
4661 | </div> | |
4662 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.h2"></a> | |
4663 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.move_constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.move_constructor">Move | |
4664 | constructor</a> | |
4665 | </h8><pre class="programlisting"><span class="identifier">packaged_task</span><span class="special">(</span> <span class="identifier">packaged_task</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4666 | </pre> | |
4667 | <div class="variablelist"> | |
4668 | <p class="title"><b></b></p> | |
4669 | <dl> | |
4670 | <dt><span class="term">Effects:</span></dt> | |
4671 | <dd><p> | |
4672 | Creates a packaged_task by moving the <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4673 | state</a> from <code class="computeroutput"><span class="identifier">other</span></code>. | |
4674 | </p></dd> | |
4675 | <dt><span class="term">Postcondition:</span></dt> | |
4676 | <dd><p> | |
4677 | <code class="computeroutput"><span class="identifier">other</span></code> contains | |
4678 | no valid shared state. | |
4679 | </p></dd> | |
4680 | <dt><span class="term">Throws:</span></dt> | |
4681 | <dd><p> | |
4682 | Nothing. | |
4683 | </p></dd> | |
4684 | </dl> | |
4685 | </div> | |
4686 | <h8><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.h3"></a> | |
4687 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.destructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.futures.packaged_task.destructor">Destructor</a> | |
4688 | </h8><pre class="programlisting"><span class="special">~</span><span class="identifier">packaged_task</span><span class="special">();</span> | |
4689 | </pre> | |
4690 | <div class="variablelist"> | |
4691 | <p class="title"><b></b></p> | |
4692 | <dl> | |
4693 | <dt><span class="term">Effects:</span></dt> | |
4694 | <dd><p> | |
4695 | Destroys <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
4696 | and abandons the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> | |
4697 | if shared state is ready; otherwise stores <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4698 | with error condition <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">broken_promise</span></code> | |
4699 | as if by <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a>: the | |
4700 | shared state is set ready. | |
4701 | </p></dd> | |
4702 | </dl> | |
4703 | </div> | |
4704 | <p> | |
4705 | </p> | |
4706 | <h5> | |
4707 | <a name="packaged_task_operator_assign_bridgehead"></a> | |
4708 | <span><a name="packaged_task_operator_assign"></a></span> | |
4709 | <a class="link" href="pooled_fixedsize.html#packaged_task_operator_assign">Member | |
4710 | function <code class="computeroutput">operator=</code>()</a> | |
4711 | </h5> | |
4712 | <p> | |
4713 | </p> | |
4714 | <pre class="programlisting"><span class="identifier">packaged_task</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">packaged_task</span> <span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4715 | </pre> | |
4716 | <div class="variablelist"> | |
4717 | <p class="title"><b></b></p> | |
4718 | <dl> | |
4719 | <dt><span class="term">Effects:</span></dt> | |
4720 | <dd><p> | |
4721 | Transfers the ownership of <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4722 | state</a> to <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. | |
4723 | </p></dd> | |
4724 | <dt><span class="term">Postcondition:</span></dt> | |
4725 | <dd><p> | |
4726 | <code class="computeroutput"><span class="identifier">other</span></code> contains | |
4727 | no valid shared state. | |
4728 | </p></dd> | |
4729 | <dt><span class="term">Throws:</span></dt> | |
4730 | <dd><p> | |
4731 | Nothing. | |
4732 | </p></dd> | |
4733 | </dl> | |
4734 | </div> | |
4735 | <p> | |
4736 | </p> | |
4737 | <h5> | |
4738 | <a name="packaged_task_swap_bridgehead"></a> | |
4739 | <span><a name="packaged_task_swap"></a></span> | |
4740 | <a class="link" href="pooled_fixedsize.html#packaged_task_swap">Member | |
4741 | function <code class="computeroutput">swap</code>()</a> | |
4742 | </h5> | |
4743 | <p> | |
4744 | </p> | |
4745 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">packaged_task</span> <span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4746 | </pre> | |
4747 | <div class="variablelist"> | |
4748 | <p class="title"><b></b></p> | |
4749 | <dl> | |
4750 | <dt><span class="term">Effects:</span></dt> | |
4751 | <dd><p> | |
4752 | Swaps the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> | |
4753 | between other and <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. | |
4754 | </p></dd> | |
4755 | <dt><span class="term">Throws:</span></dt> | |
4756 | <dd><p> | |
4757 | Nothing. | |
4758 | </p></dd> | |
4759 | </dl> | |
4760 | </div> | |
4761 | <p> | |
4762 | </p> | |
4763 | <h5> | |
4764 | <a name="packaged_task_valid_bridgehead"></a> | |
4765 | <span><a name="packaged_task_valid"></a></span> | |
4766 | <a class="link" href="pooled_fixedsize.html#packaged_task_valid">Member | |
4767 | function <code class="computeroutput">valid</code>()</a> | |
4768 | </h5> | |
4769 | <p> | |
4770 | </p> | |
4771 | <pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">valid</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4772 | </pre> | |
4773 | <div class="variablelist"> | |
4774 | <p class="title"><b></b></p> | |
4775 | <dl> | |
4776 | <dt><span class="term">Effects:</span></dt> | |
4777 | <dd><p> | |
4778 | Returns <code class="computeroutput"><span class="keyword">true</span></code> if | |
4779 | <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> | |
4780 | contains a <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a>. | |
4781 | </p></dd> | |
4782 | <dt><span class="term">Throws:</span></dt> | |
4783 | <dd><p> | |
4784 | Nothing. | |
4785 | </p></dd> | |
4786 | </dl> | |
4787 | </div> | |
4788 | <p> | |
4789 | </p> | |
4790 | <h5> | |
4791 | <a name="packaged_task_get_future_bridgehead"></a> | |
4792 | <span><a name="packaged_task_get_future"></a></span> | |
4793 | <a class="link" href="pooled_fixedsize.html#packaged_task_get_future">Member | |
4794 | function <code class="computeroutput">get_future</code>()</a> | |
4795 | </h5> | |
4796 | <p> | |
4797 | </p> | |
4798 | <pre class="programlisting"><span class="identifier">future</span><span class="special"><</span> <span class="identifier">R</span> <span class="special">></span> <span class="identifier">get_future</span><span class="special">();</span> | |
4799 | </pre> | |
4800 | <div class="variablelist"> | |
4801 | <p class="title"><b></b></p> | |
4802 | <dl> | |
4803 | <dt><span class="term">Returns:</span></dt> | |
4804 | <dd><p> | |
4805 | A <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> with the same <a class="link" href="pooled_fixedsize.html#shared_state">shared | |
4806 | state</a>. | |
4807 | </p></dd> | |
4808 | <dt><span class="term">Throws:</span></dt> | |
4809 | <dd><p> | |
4810 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4811 | with <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">future_already_retrieved</span></code> | |
4812 | or <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code>. | |
4813 | </p></dd> | |
4814 | </dl> | |
4815 | </div> | |
4816 | <p> | |
4817 | </p> | |
4818 | <h5> | |
4819 | <a name="packaged_task_operator_apply_bridgehead"></a> | |
4820 | <span><a name="packaged_task_operator_apply"></a></span> | |
4821 | <a class="link" href="pooled_fixedsize.html#packaged_task_operator_apply">Member | |
4822 | function <code class="computeroutput">operator()</code>()</a> | |
4823 | </h5> | |
4824 | <p> | |
4825 | </p> | |
4826 | <pre class="programlisting"><span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span> <span class="identifier">Args</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">args</span><span class="special">);</span> | |
4827 | </pre> | |
4828 | <div class="variablelist"> | |
4829 | <p class="title"><b></b></p> | |
4830 | <dl> | |
4831 | <dt><span class="term">Effects:</span></dt> | |
4832 | <dd><p> | |
4833 | Invokes the stored callable target. Any exception thrown by | |
4834 | the callable target <code class="computeroutput"><span class="identifier">fn</span></code> | |
4835 | is stored in the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> | |
4836 | as if by <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a>. Otherwise, | |
4837 | the value returned by <code class="computeroutput"><span class="identifier">fn</span></code> | |
4838 | is stored in the shared state as if by <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a>. | |
4839 | </p></dd> | |
4840 | <dt><span class="term">Throws:</span></dt> | |
4841 | <dd><p> | |
4842 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4843 | with <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code>. | |
4844 | </p></dd> | |
4845 | </dl> | |
4846 | </div> | |
4847 | <p> | |
4848 | </p> | |
4849 | <h5> | |
4850 | <a name="packaged_task_reset_bridgehead"></a> | |
4851 | <span><a name="packaged_task_reset"></a></span> | |
4852 | <a class="link" href="pooled_fixedsize.html#packaged_task_reset">Member | |
4853 | function <code class="computeroutput">reset</code>()</a> | |
4854 | </h5> | |
4855 | <p> | |
4856 | </p> | |
4857 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">reset</span><span class="special">();</span> | |
4858 | </pre> | |
4859 | <div class="variablelist"> | |
4860 | <p class="title"><b></b></p> | |
4861 | <dl> | |
4862 | <dt><span class="term">Effects:</span></dt> | |
4863 | <dd><p> | |
4864 | Resets the <a class="link" href="pooled_fixedsize.html#shared_state">shared state</a> | |
4865 | and abandons the result of previous executions. A new shared | |
4866 | state is constructed. | |
4867 | </p></dd> | |
4868 | <dt><span class="term">Throws:</span></dt> | |
4869 | <dd><p> | |
4870 | <code class="computeroutput"><span class="identifier">future_error</span></code> | |
4871 | with <code class="computeroutput"><span class="identifier">future_errc</span><span class="special">::</span><span class="identifier">no_state</span></code>. | |
4872 | </p></dd> | |
4873 | </dl> | |
4874 | </div> | |
4875 | <p> | |
4876 | </p> | |
4877 | <h5> | |
4878 | <a name="swap_for_packaged_task_bridgehead"></a> | |
4879 | <span><a name="swap_for_packaged_task"></a></span> | |
4880 | <a class="link" href="pooled_fixedsize.html#swap_for_packaged_task">Non-member | |
4881 | function <code class="computeroutput">swap()</code></a> | |
4882 | </h5> | |
4883 | <p> | |
4884 | </p> | |
4885 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Signature</span> <span class="special">></span> | |
4886 | <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">packaged_task</span><span class="special"><</span> <span class="identifier">Signature</span> <span class="special">></span> <span class="special">&</span> <span class="identifier">l</span><span class="special">,</span> <span class="identifier">packaged_task</span><span class="special"><</span> <span class="identifier">Signature</span> <span class="special">></span> <span class="special">&</span> <span class="identifier">r</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4887 | </pre> | |
4888 | <div class="variablelist"> | |
4889 | <p class="title"><b></b></p> | |
4890 | <dl> | |
4891 | <dt><span class="term">Effects:</span></dt> | |
4892 | <dd><p> | |
4893 | Same as <code class="computeroutput"><span class="identifier">l</span><span class="special">.</span><span class="identifier">swap</span><span class="special">(</span> | |
4894 | <span class="identifier">r</span><span class="special">)</span></code>. | |
4895 | </p></dd> | |
4896 | </dl> | |
4897 | </div> | |
4898 | </div> | |
4899 | </div> | |
4900 | </div> | |
4901 | <div class="section"> | |
4902 | <div class="titlepage"><div><div><h5 class="title"> | |
4903 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fls"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fls" title="Fiber local storage">Fiber | |
4904 | local storage</a> | |
4905 | </h5></div></div></div> | |
4906 | <h6> | |
4907 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fls.h0"></a> | |
4908 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fls.synopsis"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fls.synopsis">Synopsis</a> | |
4909 | </h6> | |
4910 | <p> | |
4911 | Fiber local storage allows a separate instance of a given data item for | |
4912 | each fiber. | |
4913 | </p> | |
4914 | <h6> | |
4915 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fls.h1"></a> | |
4916 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fls.cleanup_at_fiber_exit"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fls.cleanup_at_fiber_exit">Cleanup | |
4917 | at fiber exit</a> | |
4918 | </h6> | |
4919 | <p> | |
4920 | When a fiber exits, the objects associated with each <a class="link" href="pooled_fixedsize.html#class_fiber_specific_ptr"> <code class="computeroutput">fiber_specific_ptr</code></a> instance | |
4921 | are destroyed. By default, the object pointed to by a pointer <code class="computeroutput"><span class="identifier">p</span></code> is destroyed by invoking <code class="computeroutput"><span class="keyword">delete</span> <span class="identifier">p</span></code>, | |
4922 | but this can be overridden for a specific instance of <a class="link" href="pooled_fixedsize.html#class_fiber_specific_ptr"> <code class="computeroutput">fiber_specific_ptr</code></a> by | |
4923 | providing a cleanup routine <code class="computeroutput"><span class="identifier">func</span></code> | |
4924 | to the constructor. In this case, the object is destroyed by invoking | |
4925 | <code class="computeroutput"><span class="identifier">func</span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code>. | |
4926 | The cleanup functions are called in an unspecified order. | |
4927 | </p> | |
4928 | <p> | |
4929 | </p> | |
4930 | <h5> | |
4931 | <a name="class_fiber_specific_ptr_bridgehead"></a> | |
4932 | <span><a name="class_fiber_specific_ptr"></a></span> | |
4933 | <a class="link" href="pooled_fixedsize.html#class_fiber_specific_ptr">Class | |
4934 | <code class="computeroutput">fiber_specific_ptr</code></a> | |
4935 | </h5> | |
4936 | <p> | |
4937 | </p> | |
4938 | <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">fss</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> | |
4939 | ||
4940 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">></span> | |
4941 | <span class="keyword">class</span> <span class="identifier">fiber_specific_ptr</span> <span class="special">{</span> | |
4942 | <span class="keyword">public</span><span class="special">:</span> | |
4943 | <span class="keyword">typedef</span> <span class="identifier">T</span> <span class="identifier">element_type</span><span class="special">;</span> | |
4944 | ||
4945 | <span class="identifier">fiber_specific_ptr</span><span class="special">();</span> | |
4946 | ||
4947 | <span class="keyword">explicit</span> <span class="identifier">fiber_specific_ptr</span><span class="special">(</span> <span class="keyword">void</span><span class="special">(*</span><span class="identifier">fn</span><span class="special">)(</span><span class="identifier">T</span><span class="special">*)</span> <span class="special">);</span> | |
4948 | ||
4949 | <span class="special">~</span><span class="identifier">fiber_specific_ptr</span><span class="special">();</span> | |
4950 | ||
4951 | <span class="identifier">fiber_specific_ptr</span><span class="special">(</span> <span class="identifier">fiber_specific_ptr</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
4952 | <span class="identifier">fiber_specific_ptr</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">fiber_specific_ptr</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span> | |
4953 | ||
4954 | <span class="identifier">T</span> <span class="special">*</span> <span class="identifier">get</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4955 | ||
4956 | <span class="identifier">T</span> <span class="special">*</span> <span class="keyword">operator</span><span class="special">->()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4957 | ||
4958 | <span class="identifier">T</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">*()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
4959 | ||
4960 | <span class="identifier">T</span> <span class="special">*</span> <span class="identifier">release</span><span class="special">();</span> | |
4961 | ||
4962 | <span class="keyword">void</span> <span class="identifier">reset</span><span class="special">(</span> <span class="identifier">T</span> <span class="special">*);</span> | |
4963 | <span class="special">};</span> | |
4964 | </pre> | |
4965 | <h6> | |
4966 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fls.h2"></a> | |
4967 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fls.constructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fls.constructor">Constructor</a> | |
4968 | </h6> | |
4969 | <pre class="programlisting"><span class="identifier">fiber_specific_ptr</span><span class="special">();</span> | |
4970 | <span class="keyword">explicit</span> <span class="identifier">fiber_specific_ptr</span><span class="special">(</span> <span class="keyword">void</span><span class="special">(*</span><span class="identifier">fn</span><span class="special">)(</span><span class="identifier">T</span><span class="special">*)</span> <span class="special">);</span> | |
4971 | </pre> | |
4972 | <div class="variablelist"> | |
4973 | <p class="title"><b></b></p> | |
4974 | <dl> | |
4975 | <dt><span class="term">Requires:</span></dt> | |
4976 | <dd><p> | |
4977 | <code class="computeroutput"><span class="keyword">delete</span> <span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()</span></code> is well-formed; <code class="computeroutput"><span class="identifier">fn</span><span class="special">(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">())</span></code> | |
4978 | does not throw | |
4979 | </p></dd> | |
4980 | <dt><span class="term">Effects:</span></dt> | |
4981 | <dd><p> | |
4982 | Construct a <a class="link" href="pooled_fixedsize.html#class_fiber_specific_ptr"> <code class="computeroutput">fiber_specific_ptr</code></a> object for | |
4983 | storing a pointer to an object of type <code class="computeroutput"><span class="identifier">T</span></code> | |
4984 | specific to each fiber. When <code class="computeroutput"><span class="identifier">reset</span><span class="special">()</span></code> is called, or the fiber exits, | |
4985 | <a class="link" href="pooled_fixedsize.html#class_fiber_specific_ptr"> <code class="computeroutput">fiber_specific_ptr</code></a> calls <code class="computeroutput"><span class="identifier">fn</span><span class="special">(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">())</span></code>. If the no-arguments constructor | |
4986 | is used, the default <code class="computeroutput"><span class="keyword">delete</span></code>-based | |
4987 | cleanup function will be used to destroy the fiber-local objects. | |
4988 | </p></dd> | |
4989 | <dt><span class="term">Throws:</span></dt> | |
4990 | <dd><p> | |
4991 | <code class="computeroutput"><span class="identifier">fiber_error</span></code> if | |
4992 | an error occurs. | |
4993 | </p></dd> | |
4994 | </dl> | |
4995 | </div> | |
4996 | <h6> | |
4997 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fls.h3"></a> | |
4998 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.fls.destructor"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.fls.destructor">Destructor</a> | |
4999 | </h6> | |
5000 | <pre class="programlisting"><span class="special">~</span><span class="identifier">fiber_specific_ptr</span><span class="special">();</span> | |
5001 | </pre> | |
5002 | <div class="variablelist"> | |
5003 | <p class="title"><b></b></p> | |
5004 | <dl> | |
5005 | <dt><span class="term">Requires:</span></dt> | |
5006 | <dd><p> | |
5007 | All the fiber specific instances associated to this <a class="link" href="pooled_fixedsize.html#class_fiber_specific_ptr"> <code class="computeroutput">fiber_specific_ptr</code></a> | |
5008 | (except | |
5009 | maybe the one associated to this fiber) must be nullptr. | |
5010 | </p></dd> | |
5011 | <dt><span class="term">Effects:</span></dt> | |
5012 | <dd><p> | |
5013 | Calls <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">reset</span><span class="special">()</span></code> | |
5014 | to clean up the associated value for the current fiber, and destroys | |
5015 | <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>. | |
5016 | </p></dd> | |
5017 | <dt><span class="term">Remarks:</span></dt> | |
5018 | <dd><p> | |
5019 | The requirement is an implementation restriction. If the destructor | |
5020 | promised to delete instances for all fibers, the implementation | |
5021 | would be forced to maintain a list of all the fibers having an | |
5022 | associated specific ptr, which is against the goal of fiber specific | |
5023 | data. In general, a <a class="link" href="pooled_fixedsize.html#class_fiber_specific_ptr"> <code class="computeroutput">fiber_specific_ptr</code></a> should | |
5024 | outlive the fibers that use it. | |
5025 | </p></dd> | |
5026 | </dl> | |
5027 | </div> | |
5028 | <div class="note"><table border="0" summary="Note"> | |
5029 | <tr> | |
5030 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> | |
5031 | <th align="left">Note</th> | |
5032 | </tr> | |
5033 | <tr><td align="left" valign="top"><p> | |
5034 | Care needs to be taken to ensure that any fibers still running after | |
5035 | an instance of <a class="link" href="pooled_fixedsize.html#class_fiber_specific_ptr"> <code class="computeroutput">fiber_specific_ptr</code></a> has been destroyed | |
5036 | do not call any member functions on that instance. | |
5037 | </p></td></tr> | |
5038 | </table></div> | |
5039 | <p> | |
5040 | </p> | |
5041 | <h5> | |
5042 | <a name="fiber_specific_ptr_get_bridgehead"></a> | |
5043 | <span><a name="fiber_specific_ptr_get"></a></span> | |
5044 | <a class="link" href="pooled_fixedsize.html#fiber_specific_ptr_get">Member | |
5045 | function <code class="computeroutput">get</code>()</a> | |
5046 | </h5> | |
5047 | <p> | |
5048 | </p> | |
5049 | <pre class="programlisting"><span class="identifier">T</span> <span class="special">*</span> <span class="identifier">get</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
5050 | </pre> | |
5051 | <div class="variablelist"> | |
5052 | <p class="title"><b></b></p> | |
5053 | <dl> | |
5054 | <dt><span class="term">Returns:</span></dt> | |
5055 | <dd><p> | |
5056 | The pointer associated with the current fiber. | |
5057 | </p></dd> | |
5058 | <dt><span class="term">Throws:</span></dt> | |
5059 | <dd><p> | |
5060 | Nothing. | |
5061 | </p></dd> | |
5062 | </dl> | |
5063 | </div> | |
5064 | <div class="note"><table border="0" summary="Note"> | |
5065 | <tr> | |
5066 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> | |
5067 | <th align="left">Note</th> | |
5068 | </tr> | |
5069 | <tr><td align="left" valign="top"><p> | |
5070 | The initial value associated with an instance of <a class="link" href="pooled_fixedsize.html#class_fiber_specific_ptr"> <code class="computeroutput">fiber_specific_ptr</code></a> is | |
5071 | <code class="computeroutput"><span class="keyword">nullptr</span></code> for each fiber. | |
5072 | </p></td></tr> | |
5073 | </table></div> | |
5074 | <p> | |
5075 | </p> | |
5076 | <h5> | |
5077 | <a name="fiber_specific_ptr_operator_arrow_bridgehead"></a> | |
5078 | <span><a name="fiber_specific_ptr_operator_arrow"></a></span> | |
5079 | <a class="link" href="pooled_fixedsize.html#fiber_specific_ptr_operator_arrow">Member | |
5080 | function <code class="computeroutput">operator-></code>()</a> | |
5081 | </h5> | |
5082 | <p> | |
5083 | </p> | |
5084 | <pre class="programlisting"><span class="identifier">T</span> <span class="special">*</span> <span class="keyword">operator</span><span class="special">->()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
5085 | </pre> | |
5086 | <div class="variablelist"> | |
5087 | <p class="title"><b></b></p> | |
5088 | <dl> | |
5089 | <dt><span class="term">Requires:</span></dt> | |
5090 | <dd><p> | |
5091 | <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()</span></code> | |
5092 | is not <code class="computeroutput"><span class="keyword">nullptr</span></code>. | |
5093 | </p></dd> | |
5094 | <dt><span class="term">Returns:</span></dt> | |
5095 | <dd><p> | |
5096 | <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()</span></code> | |
5097 | </p></dd> | |
5098 | <dt><span class="term">Throws:</span></dt> | |
5099 | <dd><p> | |
5100 | Nothing. | |
5101 | </p></dd> | |
5102 | </dl> | |
5103 | </div> | |
5104 | <p> | |
5105 | </p> | |
5106 | <h5> | |
5107 | <a name="fiber_specific_ptr_operator_star_bridgehead"></a> | |
5108 | <span><a name="fiber_specific_ptr_operator_star"></a></span> | |
5109 | <a class="link" href="pooled_fixedsize.html#fiber_specific_ptr_operator_star">Member | |
5110 | function <code class="computeroutput">operator*</code>()</a> | |
5111 | </h5> | |
5112 | <p> | |
5113 | </p> | |
5114 | <pre class="programlisting"><span class="identifier">T</span> <span class="special">&</span> <span class="keyword">operator</span><span class="special">*()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="special">;</span> | |
5115 | </pre> | |
5116 | <div class="variablelist"> | |
5117 | <p class="title"><b></b></p> | |
5118 | <dl> | |
5119 | <dt><span class="term">Requires:</span></dt> | |
5120 | <dd><p> | |
5121 | <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()</span></code> | |
5122 | is not <code class="computeroutput"><span class="keyword">nullptr</span></code>. | |
5123 | </p></dd> | |
5124 | <dt><span class="term">Returns:</span></dt> | |
5125 | <dd><p> | |
5126 | <code class="computeroutput"><span class="special">*(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">())</span></code> | |
5127 | </p></dd> | |
5128 | <dt><span class="term">Throws:</span></dt> | |
5129 | <dd><p> | |
5130 | Nothing. | |
5131 | </p></dd> | |
5132 | </dl> | |
5133 | </div> | |
5134 | <p> | |
5135 | </p> | |
5136 | <h5> | |
5137 | <a name="fiber_specific_ptr_release_bridgehead"></a> | |
5138 | <span><a name="fiber_specific_ptr_release"></a></span> | |
5139 | <a class="link" href="pooled_fixedsize.html#fiber_specific_ptr_release">Member | |
5140 | function <code class="computeroutput">release</code>()</a> | |
5141 | </h5> | |
5142 | <p> | |
5143 | </p> | |
5144 | <pre class="programlisting"><span class="identifier">T</span> <span class="special">*</span> <span class="identifier">release</span><span class="special">();</span> | |
5145 | </pre> | |
5146 | <div class="variablelist"> | |
5147 | <p class="title"><b></b></p> | |
5148 | <dl> | |
5149 | <dt><span class="term">Effects:</span></dt> | |
5150 | <dd><p> | |
5151 | Return <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()</span></code> | |
5152 | and store <code class="computeroutput"><span class="keyword">nullptr</span></code> | |
5153 | as the pointer associated with the current fiber without invoking | |
5154 | the cleanup function. | |
5155 | </p></dd> | |
5156 | <dt><span class="term">Postcondition:</span></dt> | |
5157 | <dd><p> | |
5158 | <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()==</span><span class="keyword">nullptr</span></code> | |
5159 | </p></dd> | |
5160 | <dt><span class="term">Throws:</span></dt> | |
5161 | <dd><p> | |
5162 | Nothing. | |
5163 | </p></dd> | |
5164 | </dl> | |
5165 | </div> | |
5166 | <p> | |
5167 | </p> | |
5168 | <h5> | |
5169 | <a name="fiber_specific_ptr_reset_bridgehead"></a> | |
5170 | <span><a name="fiber_specific_ptr_reset"></a></span> | |
5171 | <a class="link" href="pooled_fixedsize.html#fiber_specific_ptr_reset">Member | |
5172 | function <code class="computeroutput">reset</code>()</a> | |
5173 | </h5> | |
5174 | <p> | |
5175 | </p> | |
5176 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">reset</span><span class="special">(</span> <span class="identifier">T</span> <span class="special">*</span> <span class="identifier">new_value</span><span class="special">);</span> | |
5177 | </pre> | |
5178 | <div class="variablelist"> | |
5179 | <p class="title"><b></b></p> | |
5180 | <dl> | |
5181 | <dt><span class="term">Effects:</span></dt> | |
5182 | <dd><p> | |
5183 | If <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()!=</span><span class="identifier">new_value</span></code> and <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()</span></code> is not <code class="computeroutput"><span class="keyword">nullptr</span></code>, | |
5184 | invoke <code class="computeroutput"><span class="keyword">delete</span> <span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">fn</span><span class="special">(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">())</span></code> as appropriate. Store <code class="computeroutput"><span class="identifier">new_value</span></code> as the pointer associated | |
5185 | with the current fiber. | |
5186 | </p></dd> | |
5187 | <dt><span class="term">Postcondition:</span></dt> | |
5188 | <dd><p> | |
5189 | <code class="computeroutput"><span class="keyword">this</span><span class="special">-></span><span class="identifier">get</span><span class="special">()==</span><span class="identifier">new_value</span></code> | |
5190 | </p></dd> | |
5191 | <dt><span class="term">Throws:</span></dt> | |
5192 | <dd><p> | |
5193 | Exception raised during cleanup of previous value. | |
5194 | </p></dd> | |
5195 | </dl> | |
5196 | </div> | |
5197 | </div> | |
5198 | <div class="section"> | |
5199 | <div class="titlepage"><div><div><h5 class="title"> | |
5200 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration"></a><a name="migration"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration" title="Migrating fibers between threads">Migrating | |
5201 | fibers between threads</a> | |
5202 | </h5></div></div></div> | |
5203 | <h6> | |
5204 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.h0"></a> | |
5205 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.overview"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.overview">Overview</a> | |
5206 | </h6> | |
5207 | <p> | |
5208 | Each fiber owns a stack and manages its execution state, including all | |
5209 | registers and CPU flags, the instruction pointer and the stack pointer. | |
5210 | That means, in general, a fiber is not bound to a specific thread.<sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.f0" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.migration.f0" class="footnote">3</a>]</sup> <sup>,</sup><sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.f1" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.migration.f1" class="footnote">4</a>]</sup> | |
5211 | </p> | |
5212 | <p> | |
5213 | Migrating a fiber from a logical CPU with heavy workload to another logical | |
5214 | CPU with a lighter workload might speed up the overall execution. Note | |
5215 | that in the case of NUMA-architectures, it is not always advisable to | |
5216 | migrate data between threads. Suppose fiber <span class="emphasis"><em>f</em></span> is | |
5217 | running on logical CPU <span class="emphasis"><em>cpu0</em></span> which belongs to NUMA | |
5218 | node <span class="emphasis"><em>node0</em></span>. The data of <span class="emphasis"><em>f</em></span> are | |
5219 | allocated on the physical memory located at <span class="emphasis"><em>node0</em></span>. | |
5220 | Migrating the fiber from <span class="emphasis"><em>cpu0</em></span> to another logical | |
5221 | CPU <span class="emphasis"><em>cpuX</em></span> which is part of a different NUMA node | |
5222 | <span class="emphasis"><em>nodeX</em></span> might reduce the performance of the application | |
5223 | due to increased latency of memory access. | |
5224 | </p> | |
5225 | <p> | |
5226 | Only fibers that are contained in <a class="link" href="../../scheduling.html#class_sched_algorithm"> <code class="computeroutput">sched_algorithm</code></a>'s | |
5227 | ready queue can migrate between threads. You cannot migrate a running | |
5228 | fiber, nor one that is <a class="link" href="../../overview.html#blocking"><span class="emphasis"><em>blocked</em></span></a>. | |
5229 | </p> | |
5230 | <p> | |
5231 | In<span class="bold"><strong>Boost.Fiber</strong></span> a fiber is migrated by | |
5232 | invoking <a class="link" href="../../scheduling.html#context_migrate"> <code class="computeroutput">context::migrate()</code></a> on the <a class="link" href="../../scheduling.html#class_context"> <code class="computeroutput">context</code></a> instance | |
5233 | for a fiber already associated with the destination thread, passing the | |
5234 | <code class="computeroutput"><span class="identifier">context</span></code> for the fiber | |
5235 | to be migrated. | |
5236 | </p> | |
5237 | <h6> | |
5238 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.h1"></a> | |
5239 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.example_of_work_sharing"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.example_of_work_sharing">Example | |
5240 | of work sharing</a> | |
5241 | </h6> | |
5242 | <p> | |
5243 | In the example <a href="../../../../../examples/work_sharing.cpp" target="_top">work_sharing.cpp</a> | |
5244 | multiple worker fibers are created on the main thread. Each fiber gets | |
5245 | a character as parameter at construction. This character is printed out | |
5246 | ten times. Between each iteration the fiber calls <a class="link" href="../../fiber_mgmt/this_fiber.html#this_fiber_yield"> <code class="computeroutput">this_fiber::yield()</code></a>. | |
5247 | That puts the fiber in the ready queue of the fiber-scheduler <span class="emphasis"><em>shared_ready_queue</em></span>, | |
5248 | running in the current thread. The next fiber ready to be executed is | |
5249 | dequeued from the shared ready queue and resumed by <span class="emphasis"><em>shared_ready_queue</em></span> | |
5250 | running on <span class="emphasis"><em>any participating thread</em></span>. | |
5251 | </p> | |
5252 | <p> | |
5253 | All instances of <span class="emphasis"><em>shared_ready_queue</em></span> share one global | |
5254 | concurrent queue, used as ready queue. This mechanism shares all worker | |
5255 | fibers between all instances of <span class="emphasis"><em>shared_ready_queue</em></span>, | |
5256 | thus between all participating threads. | |
5257 | </p> | |
5258 | <h6> | |
5259 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.h2"></a> | |
5260 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.setup_of_threads_and_fibers"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.setup_of_threads_and_fibers">Setup | |
5261 | of threads and fibers</a> | |
5262 | </h6> | |
5263 | <p> | |
5264 | In <code class="computeroutput"><span class="identifier">main</span><span class="special">()</span></code> | |
5265 | the fiber-scheduler is installed and the worker fibers and the threads | |
5266 | are launched. | |
5267 | </p> | |
5268 | <p> | |
5269 | </p> | |
5270 | <pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">use_scheduling_algorithm</span><span class="special"><</span> <span class="identifier">shared_ready_queue</span> <span class="special">>();</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c0" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c1"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> | |
5271 | ||
5272 | <span class="keyword">for</span> <span class="special">(</span> <span class="keyword">char</span> <span class="identifier">c</span> <span class="special">:</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">(</span><span class="string">"abcdefghijklmnopqrstuvwxyz"</span><span class="special">))</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c2" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c3"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> | |
5273 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span><span class="special">([</span><span class="identifier">c</span><span class="special">](){</span> <span class="identifier">whatevah</span><span class="special">(</span> <span class="identifier">c</span><span class="special">);</span> <span class="special">}).</span><span class="identifier">detach</span><span class="special">();</span> | |
5274 | <span class="special">++</span><span class="identifier">fiber_count</span><span class="special">;</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c4" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c5"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> | |
5275 | <span class="special">}</span> | |
5276 | <span class="identifier">barrier</span> <span class="identifier">b</span><span class="special">(</span> <span class="number">4</span><span class="special">);</span> | |
5277 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">thread</span> <span class="identifier">threads</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c6" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c7"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a> | |
5278 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">thread</span><span class="special">(</span> <span class="identifier">thread</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">b</span><span class="special">),</span> | |
5279 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">thread</span><span class="special">(</span> <span class="identifier">thread</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">b</span><span class="special">),</span> | |
5280 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">thread</span><span class="special">(</span> <span class="identifier">thread</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">b</span><span class="special">)</span> | |
5281 | <span class="special">};</span> | |
5282 | <span class="identifier">b</span><span class="special">.</span><span class="identifier">wait</span><span class="special">();</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c8" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c9"><img src="../../../../../../../doc/src/images/callouts/5.png" alt="5" border="0"></a> | |
5283 | <span class="special">{</span> | |
5284 | <span class="identifier">lock_t</span><a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c10" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c11"><img src="../../../../../../../doc/src/images/callouts/6.png" alt="6" border="0"></a> <span class="identifier">lk</span><span class="special">(</span> <span class="identifier">mtx_count</span><span class="special">);</span> | |
5285 | <span class="identifier">cnd_count</span><span class="special">.</span><span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">,</span> <span class="special">[](){</span> <span class="keyword">return</span> <span class="number">0</span> <span class="special">==</span> <span class="identifier">fiber_count</span><span class="special">;</span> <span class="special">}</span> <span class="special">);</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c12" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c13"><img src="../../../../../../../doc/src/images/callouts/7.png" alt="7" border="0"></a> | |
5286 | <span class="special">}</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c14" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c15"><img src="../../../../../../../doc/src/images/callouts/8.png" alt="8" border="0"></a> | |
5287 | <span class="identifier">BOOST_ASSERT</span><span class="special">(</span> <span class="number">0</span> <span class="special">==</span> <span class="identifier">fiber_count</span><span class="special">);</span> | |
5288 | <span class="keyword">for</span> <span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">thread</span> <span class="special">&</span> <span class="identifier">t</span> <span class="special">:</span> <span class="identifier">threads</span><span class="special">)</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c16" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c17"><img src="../../../../../../../doc/src/images/callouts/9.png" alt="9" border="0"></a> | |
5289 | <span class="identifier">t</span><span class="special">.</span><span class="identifier">join</span><span class="special">();</span> | |
5290 | <span class="special">}</span> | |
5291 | </pre> | |
5292 | <p> | |
5293 | </p> | |
5294 | <div class="calloutlist"><table border="0" summary="Callout list"> | |
5295 | <tr> | |
5296 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c1"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c0"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> </p></td> | |
5297 | <td valign="top" align="left"><p> | |
5298 | Install the scheduling algorithm <code class="computeroutput"><span class="identifier">shared_ready_queue</span></code> | |
5299 | in the main thread too, so each new fiber gets launched into the | |
5300 | shared pool. | |
5301 | </p></td> | |
5302 | </tr> | |
5303 | <tr> | |
5304 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c3"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c2"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> </p></td> | |
5305 | <td valign="top" align="left"><p> | |
5306 | Launch a number of worker fibers; each worker fiber picks up a character | |
5307 | that is passed as parameter to fiber-function <code class="computeroutput"><span class="identifier">whatevah</span></code>. | |
5308 | Each worker fiber gets detached. | |
5309 | </p></td> | |
5310 | </tr> | |
5311 | <tr> | |
5312 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c5"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c4"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> </p></td> | |
5313 | <td valign="top" align="left"><p> | |
5314 | Increment fiber counter for each new fiber. | |
5315 | </p></td> | |
5316 | </tr> | |
5317 | <tr> | |
5318 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c7"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c6"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a> </p></td> | |
5319 | <td valign="top" align="left"><p> | |
5320 | Launch a couple of threads that join the work sharing. | |
5321 | </p></td> | |
5322 | </tr> | |
5323 | <tr> | |
5324 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c9"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c8"><img src="../../../../../../../doc/src/images/callouts/5.png" alt="5" border="0"></a> </p></td> | |
5325 | <td valign="top" align="left"><p> | |
5326 | sync with other threads: allow them to start processing | |
5327 | </p></td> | |
5328 | </tr> | |
5329 | <tr> | |
5330 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c11"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c10"><img src="../../../../../../../doc/src/images/callouts/6.png" alt="6" border="0"></a> </p></td> | |
5331 | <td valign="top" align="left"><p> | |
5332 | <code class="computeroutput"><span class="identifier">lock_t</span></code> is typedef'ed | |
5333 | as <a href="http://en.cppreference.com/w/cpp/thread/unique_lock" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span></code></a>< <a href="http://en.cppreference.com/w/cpp/thread/mutex" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">mutex</span></code></a> > | |
5334 | </p></td> | |
5335 | </tr> | |
5336 | <tr> | |
5337 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c13"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c12"><img src="../../../../../../../doc/src/images/callouts/7.png" alt="7" border="0"></a> </p></td> | |
5338 | <td valign="top" align="left"><p> | |
5339 | Suspend main fiber and resume worker fibers in the meanwhile. Main | |
5340 | fiber gets resumed (e.g returns from <code class="computeroutput"><span class="identifier">condition_variable_any</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code>) if all worker fibers are complete. | |
5341 | </p></td> | |
5342 | </tr> | |
5343 | <tr> | |
5344 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c15"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c14"><img src="../../../../../../../doc/src/images/callouts/8.png" alt="8" border="0"></a> </p></td> | |
5345 | <td valign="top" align="left"><p> | |
5346 | Releasing lock of mtx_count is required before joining the threads, | |
5347 | othwerwise the other threads would be blocked inside condition_variable::wait() | |
5348 | and would never return (deadlock). | |
5349 | </p></td> | |
5350 | </tr> | |
5351 | <tr> | |
5352 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c17"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c16"><img src="../../../../../../../doc/src/images/callouts/9.png" alt="9" border="0"></a> </p></td> | |
5353 | <td valign="top" align="left"><p> | |
5354 | wait for threads to terminate | |
5355 | </p></td> | |
5356 | </tr> | |
5357 | </table></div> | |
5358 | <p> | |
5359 | The start of the threads is synchronized with a barrier. The main fiber | |
5360 | of each thread (including main thread) is suspended until all worker | |
5361 | fibers are complete. When the main fiber returns from <a class="link" href="pooled_fixedsize.html#condition_variable_wait"> <code class="computeroutput">condition_variable::wait()</code></a>, | |
5362 | the thread terminates: the main thread joins all other threads. | |
5363 | </p> | |
5364 | <p> | |
5365 | </p> | |
5366 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">thread</span><span class="special">(</span> <span class="identifier">barrier</span> <span class="special">*</span> <span class="identifier">b</span><span class="special">)</span> <span class="special">{</span> | |
5367 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostringstream</span> <span class="identifier">buffer</span><span class="special">;</span> | |
5368 | <span class="identifier">buffer</span> <span class="special"><<</span> <span class="string">"thread started "</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">this_thread</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
5369 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">str</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">flush</span><span class="special">;</span> | |
5370 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">use_scheduling_algorithm</span><span class="special"><</span> <span class="identifier">shared_ready_queue</span> <span class="special">>();</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c18" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c19"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> | |
5371 | <span class="identifier">b</span><span class="special">-></span><span class="identifier">wait</span><span class="special">();</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c20" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c21"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> | |
5372 | <span class="identifier">lock_t</span> <span class="identifier">lk</span><span class="special">(</span> <span class="identifier">mtx_count</span><span class="special">);</span> | |
5373 | <span class="identifier">cnd_count</span><span class="special">.</span><span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">,</span> <span class="special">[](){</span> <span class="keyword">return</span> <span class="number">0</span> <span class="special">==</span> <span class="identifier">fiber_count</span><span class="special">;</span> <span class="special">}</span> <span class="special">);</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c22" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c23"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> | |
5374 | <span class="identifier">BOOST_ASSERT</span><span class="special">(</span> <span class="number">0</span> <span class="special">==</span> <span class="identifier">fiber_count</span><span class="special">);</span> | |
5375 | <span class="special">}</span> | |
5376 | </pre> | |
5377 | <p> | |
5378 | </p> | |
5379 | <div class="calloutlist"><table border="0" summary="Callout list"> | |
5380 | <tr> | |
5381 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c19"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c18"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> </p></td> | |
5382 | <td valign="top" align="left"><p> | |
5383 | Install the scheduling algorithm <code class="computeroutput"><span class="identifier">shared_ready_queue</span></code> | |
5384 | in order to join the work sharing. | |
5385 | </p></td> | |
5386 | </tr> | |
5387 | <tr> | |
5388 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c21"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c20"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> </p></td> | |
5389 | <td valign="top" align="left"><p> | |
5390 | sync with other threads: allow them to start processing | |
5391 | </p></td> | |
5392 | </tr> | |
5393 | <tr> | |
5394 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c23"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c22"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> </p></td> | |
5395 | <td valign="top" align="left"><p> | |
5396 | Suspend main fiber and resume worker fibers in the meanwhile. Main | |
5397 | fiber gets resumed (e.g returns from <code class="computeroutput"><span class="identifier">condition_variable_any</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code>) if all worker fibers are complete. | |
5398 | </p></td> | |
5399 | </tr> | |
5400 | </table></div> | |
5401 | <p> | |
5402 | Each worker fiber executes function <code class="computeroutput"><span class="identifier">whatevah</span><span class="special">()</span></code> with character <code class="computeroutput"><span class="identifier">me</span></code> | |
5403 | as parameter. The fiber yields in a loop and prints out a message if | |
5404 | it was migrated to another thread. | |
5405 | </p> | |
5406 | <p> | |
5407 | </p> | |
5408 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">whatevah</span><span class="special">(</span> <span class="keyword">char</span> <span class="identifier">me</span><span class="special">)</span> <span class="special">{</span> | |
5409 | <span class="keyword">try</span> <span class="special">{</span> | |
5410 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">thread</span><span class="special">::</span><span class="identifier">id</span> <span class="identifier">my_thread</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">this_thread</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">();</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c24" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c25"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> | |
5411 | <span class="special">{</span> | |
5412 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostringstream</span> <span class="identifier">buffer</span><span class="special">;</span> | |
5413 | <span class="identifier">buffer</span> <span class="special"><<</span> <span class="string">"fiber "</span> <span class="special"><<</span> <span class="identifier">me</span> <span class="special"><<</span> <span class="string">" started on thread "</span> <span class="special"><<</span> <span class="identifier">my_thread</span> <span class="special"><<</span> <span class="char">'\n'</span><span class="special">;</span> | |
5414 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">str</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">flush</span><span class="special">;</span> | |
5415 | <span class="special">}</span> | |
5416 | <span class="keyword">for</span> <span class="special">(</span> <span class="keyword">unsigned</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">10</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c26" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c27"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> | |
5417 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">yield</span><span class="special">();</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c28" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c29"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> | |
5418 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">thread</span><span class="special">::</span><span class="identifier">id</span> <span class="identifier">new_thread</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">this_thread</span><span class="special">::</span><span class="identifier">get_id</span><span class="special">();</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c30" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c31"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a> | |
5419 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">new_thread</span> <span class="special">!=</span> <span class="identifier">my_thread</span><span class="special">)</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c32" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c33"><img src="../../../../../../../doc/src/images/callouts/5.png" alt="5" border="0"></a> | |
5420 | <span class="identifier">my_thread</span> <span class="special">=</span> <span class="identifier">new_thread</span><span class="special">;</span> | |
5421 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostringstream</span> <span class="identifier">buffer</span><span class="special">;</span> | |
5422 | <span class="identifier">buffer</span> <span class="special"><<</span> <span class="string">"fiber "</span> <span class="special"><<</span> <span class="identifier">me</span> <span class="special"><<</span> <span class="string">" switched to thread "</span> <span class="special"><<</span> <span class="identifier">my_thread</span> <span class="special"><<</span> <span class="char">'\n'</span><span class="special">;</span> | |
5423 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">str</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">flush</span><span class="special">;</span> | |
5424 | <span class="special">}</span> | |
5425 | <span class="special">}</span> | |
5426 | <span class="special">}</span> <span class="keyword">catch</span> <span class="special">(</span> <span class="special">...</span> <span class="special">)</span> <span class="special">{</span> | |
5427 | <span class="special">}</span> | |
5428 | <span class="identifier">lock_t</span> <span class="identifier">lk</span><span class="special">(</span> <span class="identifier">mtx_count</span><span class="special">);</span> | |
5429 | <span class="keyword">if</span> <span class="special">(</span> <span class="number">0</span> <span class="special">==</span> <span class="special">--</span><span class="identifier">fiber_count</span><span class="special">)</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c34" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c35"><img src="../../../../../../../doc/src/images/callouts/6.png" alt="6" border="0"></a> | |
5430 | <span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span> | |
5431 | <span class="identifier">cnd_count</span><span class="special">.</span><span class="identifier">notify_all</span><span class="special">();</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c36" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c37"><img src="../../../../../../../doc/src/images/callouts/7.png" alt="7" border="0"></a> | |
5432 | <span class="special">}</span> | |
5433 | <span class="special">}</span> | |
5434 | </pre> | |
5435 | <p> | |
5436 | </p> | |
5437 | <div class="calloutlist"><table border="0" summary="Callout list"> | |
5438 | <tr> | |
5439 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c25"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c24"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> </p></td> | |
5440 | <td valign="top" align="left"><p> | |
5441 | get ID of initial thread | |
5442 | </p></td> | |
5443 | </tr> | |
5444 | <tr> | |
5445 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c27"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c26"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> </p></td> | |
5446 | <td valign="top" align="left"><p> | |
5447 | loop ten times | |
5448 | </p></td> | |
5449 | </tr> | |
5450 | <tr> | |
5451 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c29"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c28"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> </p></td> | |
5452 | <td valign="top" align="left"><p> | |
5453 | yield to other fibers | |
5454 | </p></td> | |
5455 | </tr> | |
5456 | <tr> | |
5457 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c31"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c30"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a> </p></td> | |
5458 | <td valign="top" align="left"><p> | |
5459 | get ID of current thread | |
5460 | </p></td> | |
5461 | </tr> | |
5462 | <tr> | |
5463 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c33"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c32"><img src="../../../../../../../doc/src/images/callouts/5.png" alt="5" border="0"></a> </p></td> | |
5464 | <td valign="top" align="left"><p> | |
5465 | test if fiber was migrated to another thread | |
5466 | </p></td> | |
5467 | </tr> | |
5468 | <tr> | |
5469 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c35"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c34"><img src="../../../../../../../doc/src/images/callouts/6.png" alt="6" border="0"></a> </p></td> | |
5470 | <td valign="top" align="left"><p> | |
5471 | Decrement fiber counter for each completed fiber. | |
5472 | </p></td> | |
5473 | </tr> | |
5474 | <tr> | |
5475 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c37"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c36"><img src="../../../../../../../doc/src/images/callouts/7.png" alt="7" border="0"></a> </p></td> | |
5476 | <td valign="top" align="left"><p> | |
5477 | Notify all fibers waiting on <code class="computeroutput"><span class="identifier">cnd_count</span></code>. | |
5478 | </p></td> | |
5479 | </tr> | |
5480 | </table></div> | |
5481 | <h6> | |
5482 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.h3"></a> | |
5483 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.scheduling_fibers"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.scheduling_fibers">Scheduling | |
5484 | fibers</a> | |
5485 | </h6> | |
5486 | <p> | |
5487 | The fiber scheduler <code class="computeroutput"><span class="identifier">shared_ready_queue</span></code> | |
5488 | is like <code class="computeroutput"><span class="identifier">round_robin</span></code>, | |
5489 | except that it shares a common ready queue among all participating threads. | |
5490 | A thread participates in this pool by executing <a class="link" href="../../fiber_mgmt/fiber.html#use_scheduling_algorithm"> <code class="computeroutput">use_scheduling_algorithm()</code></a> | |
5491 | before | |
5492 | any other <span class="bold"><strong>Boost.Fiber</strong></span> operation. | |
5493 | </p> | |
5494 | <p> | |
5495 | The important point about the ready queue is that it's a class static, | |
5496 | common to all instances of shared_ready_queue. Fibers that are enqueued | |
5497 | via <a class="link" href="../../scheduling.html#sched_algorithm_awakened"> <code class="computeroutput">sched_algorithm::awakened()</code></a> (fibers that are | |
5498 | ready to be resumed) are thus available to all threads. It is required | |
5499 | to reserve a separate, scheduler-specific queue for the thread's main | |
5500 | fiber and dispatcher fibers: these may <span class="emphasis"><em>not</em></span> be shared | |
5501 | between threads! When we're passed either of these fibers, push it there | |
5502 | instead of in the shared queue: it would be Bad News for thread B to | |
5503 | retrieve and attempt to execute thread A's main fiber. | |
5504 | </p> | |
5505 | <p> | |
5506 | </p> | |
5507 | <pre class="programlisting"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">awakened</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">*</span> <span class="identifier">ctx</span><span class="special">)</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
5508 | <span class="identifier">BOOST_ASSERT</span><span class="special">(</span> <span class="keyword">nullptr</span> <span class="special">!=</span> <span class="identifier">ctx</span><span class="special">);</span> | |
5509 | ||
5510 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">ctx</span><span class="special">-></span><span class="identifier">is_context</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">type</span><span class="special">::</span><span class="identifier">pinned_context</span><span class="special">)</span> <span class="special">)</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c38" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c39"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> | |
5511 | <span class="identifier">local_queue_</span><span class="special">.</span><span class="identifier">push</span><span class="special">(</span> <span class="identifier">ctx</span><span class="special">);</span> | |
5512 | <span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span> | |
5513 | <span class="identifier">lock_t</span> <span class="identifier">lk</span><span class="special">(</span><span class="identifier">rqueue_mtx_</span><span class="special">);</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c40" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c41"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> | |
5514 | <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">push</span><span class="special">(</span> <span class="identifier">ctx</span><span class="special">);</span> | |
5515 | <span class="special">}</span> | |
5516 | <span class="special">}</span> | |
5517 | </pre> | |
5518 | <p> | |
5519 | </p> | |
5520 | <div class="calloutlist"><table border="0" summary="Callout list"> | |
5521 | <tr> | |
5522 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c39"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c38"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> </p></td> | |
5523 | <td valign="top" align="left"><p> | |
5524 | recognize when we're passed this thread's main fiber (or an implicit | |
5525 | library helper fiber): never put those on the shared queue | |
5526 | </p></td> | |
5527 | </tr> | |
5528 | <tr> | |
5529 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c41"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c40"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> </p></td> | |
5530 | <td valign="top" align="left"><p> | |
5531 | worker fiber, enqueue on shared queue | |
5532 | </p></td> | |
5533 | </tr> | |
5534 | </table></div> | |
5535 | <p> | |
5536 | When <a class="link" href="../../scheduling.html#sched_algorithm_pick_next"> <code class="computeroutput">sched_algorithm::pick_next()</code></a> gets called | |
5537 | inside one thread, a fiber is dequeued from <span class="emphasis"><em>rqueue_</em></span> | |
5538 | and will be resumed in that thread. | |
5539 | </p> | |
5540 | <p> | |
5541 | </p> | |
5542 | <pre class="programlisting"><span class="keyword">virtual</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">*</span> <span class="identifier">pick_next</span><span class="special">()</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
5543 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">*</span> <span class="identifier">ctx</span><span class="special">(</span> <span class="keyword">nullptr</span><span class="special">);</span> | |
5544 | <span class="identifier">lock_t</span> <span class="identifier">lk</span><span class="special">(</span><span class="identifier">rqueue_mtx_</span><span class="special">);</span> | |
5545 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">empty</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c42" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c43"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> | |
5546 | <span class="identifier">ctx</span> <span class="special">=</span> <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">front</span><span class="special">();</span> | |
5547 | <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">pop</span><span class="special">();</span> | |
5548 | <span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span> | |
5549 | <span class="identifier">BOOST_ASSERT</span><span class="special">(</span> <span class="keyword">nullptr</span> <span class="special">!=</span> <span class="identifier">ctx</span><span class="special">);</span> | |
5550 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span><span class="special">::</span><span class="identifier">active</span><span class="special">()-></span><span class="identifier">migrate</span><span class="special">(</span> <span class="identifier">ctx</span><span class="special">);</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c44" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c45"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> | |
5551 | <span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span> | |
5552 | <span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span> | |
5553 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">local_queue_</span><span class="special">.</span><span class="identifier">empty</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c46" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c47"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> | |
5554 | <span class="identifier">ctx</span> <span class="special">=</span> <span class="identifier">local_queue_</span><span class="special">.</span><span class="identifier">front</span><span class="special">();</span> | |
5555 | <span class="identifier">local_queue_</span><span class="special">.</span><span class="identifier">pop</span><span class="special">();</span> | |
5556 | <span class="special">}</span> | |
5557 | <span class="special">}</span> | |
5558 | <span class="keyword">return</span> <span class="identifier">ctx</span><span class="special">;</span> | |
5559 | <span class="special">}</span> | |
5560 | </pre> | |
5561 | <p> | |
5562 | </p> | |
5563 | <div class="calloutlist"><table border="0" summary="Callout list"> | |
5564 | <tr> | |
5565 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c43"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c42"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> </p></td> | |
5566 | <td valign="top" align="left"><p> | |
5567 | pop an item from the ready queue | |
5568 | </p></td> | |
5569 | </tr> | |
5570 | <tr> | |
5571 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c45"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c44"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> </p></td> | |
5572 | <td valign="top" align="left"><p> | |
5573 | attach context to current scheduler via the active fiber of this | |
5574 | thread; benign if the fiber already belongs to this thread | |
5575 | </p></td> | |
5576 | </tr> | |
5577 | <tr> | |
5578 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c47"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.c46"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> </p></td> | |
5579 | <td valign="top" align="left"><p> | |
5580 | nothing in the ready queue, return main or dispatcher fiber | |
5581 | </p></td> | |
5582 | </tr> | |
5583 | </table></div> | |
5584 | <p> | |
5585 | The source code above is found in <a href="../../../../../examples/work_sharing.cpp" target="_top">work_sharing.cpp</a>. | |
5586 | </p> | |
5587 | </div> | |
5588 | <div class="section"> | |
5589 | <div class="titlepage"><div><div><h5 class="title"> | |
5590 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks"></a><a name="callbacks"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks" title="Integrating Fibers with Asynchronous Callbacks">Integrating | |
5591 | Fibers with Asynchronous Callbacks</a> | |
5592 | </h5></div></div></div> | |
5593 | <h6> | |
5594 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.h0"></a> | |
5595 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.overview"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.overview">Overview</a> | |
5596 | </h6> | |
5597 | <p> | |
5598 | One of the primary benefits of <span class="bold"><strong>Boost.Fiber</strong></span> | |
5599 | is the ability to use asynchronous operations for efficiency, while at | |
5600 | the same time structuring the calling code <span class="emphasis"><em>as if</em></span> | |
5601 | the operations were synchronous. Asynchronous operations provide completion | |
5602 | notification in a variety of ways, but most involve a callback function | |
5603 | of some kind. This section discusses tactics for interfacing <span class="bold"><strong>Boost.Fiber</strong></span> with an arbitrary async operation. | |
5604 | </p> | |
5605 | <p> | |
5606 | For purposes of illustration, consider the following hypothetical API: | |
5607 | </p> | |
5608 | <p> | |
5609 | </p> | |
5610 | <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">AsyncAPI</span> <span class="special">{</span> | |
5611 | <span class="keyword">public</span><span class="special">:</span> | |
5612 | <span class="comment">// constructor acquires some resource that can be read and written</span> | |
5613 | <span class="identifier">AsyncAPI</span><span class="special">();</span> | |
5614 | ||
5615 | <span class="comment">// callbacks accept an int error code; 0 == success</span> | |
5616 | <span class="keyword">typedef</span> <span class="keyword">int</span> <span class="identifier">errorcode</span><span class="special">;</span> | |
5617 | ||
5618 | <span class="comment">// write callback only needs to indicate success or failure</span> | |
5619 | <span class="keyword">void</span> <span class="identifier">init_write</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">data</span><span class="special">,</span> | |
5620 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span> <span class="keyword">void</span><span class="special">(</span> <span class="identifier">errorcode</span><span class="special">)</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">callback</span><span class="special">);</span> | |
5621 | ||
5622 | <span class="comment">// read callback needs to accept both errorcode and data</span> | |
5623 | <span class="keyword">void</span> <span class="identifier">init_read</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span> <span class="keyword">void</span><span class="special">(</span> <span class="identifier">errorcode</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">></span> <span class="keyword">const</span><span class="special">&);</span> | |
5624 | ||
5625 | <span class="comment">// ... other operations ...</span> | |
5626 | <span class="special">};</span> | |
5627 | </pre> | |
5628 | <p> | |
5629 | </p> | |
5630 | <p> | |
5631 | The significant points about each of <code class="computeroutput"><span class="identifier">init_write</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">init_read</span><span class="special">()</span></code> are: | |
5632 | </p> | |
5633 | <div class="itemizedlist"><ul class="itemizedlist" type="disc"> | |
5634 | <li class="listitem"> | |
5635 | The <code class="computeroutput"><span class="identifier">AsyncAPI</span></code> method | |
5636 | only initiates the operation. It returns immediately, while the requested | |
5637 | operation is still pending. | |
5638 | </li> | |
5639 | <li class="listitem"> | |
5640 | The method accepts a callback. When the operation completes, the | |
5641 | callback is called with relevant parameters (error code, data if | |
5642 | applicable). | |
5643 | </li> | |
5644 | </ul></div> | |
5645 | <p> | |
5646 | We would like to wrap these asynchronous methods in functions that appear | |
5647 | synchronous by blocking the calling fiber until the operation completes. | |
5648 | This lets us use the wrapper function's return value to deliver relevant | |
5649 | data. | |
5650 | </p> | |
5651 | <div class="tip"><table border="0" summary="Tip"> | |
5652 | <tr> | |
5653 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../../doc/src/images/tip.png"></td> | |
5654 | <th align="left">Tip</th> | |
5655 | </tr> | |
5656 | <tr><td align="left" valign="top"><p> | |
5657 | <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a> and <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> are your | |
5658 | friends here. | |
5659 | </p></td></tr> | |
5660 | </table></div> | |
5661 | <h6> | |
5662 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.h1"></a> | |
5663 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.return_errorcode"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.return_errorcode">Return | |
5664 | Errorcode</a> | |
5665 | </h6> | |
5666 | <p> | |
5667 | The <code class="computeroutput"><span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">init_write</span><span class="special">()</span></code> | |
5668 | callback passes only an <code class="computeroutput"><span class="identifier">errorcode</span></code>. | |
5669 | If we simply want the blocking wrapper to return that <code class="computeroutput"><span class="identifier">errorcode</span></code>, | |
5670 | this is an extremely straightforward use of <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a> and | |
5671 | <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a>: | |
5672 | </p> | |
5673 | <p> | |
5674 | </p> | |
5675 | <pre class="programlisting"><span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">errorcode</span> <span class="identifier">write_ec</span><span class="special">(</span> <span class="identifier">AsyncAPI</span> <span class="special">&</span> <span class="identifier">api</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">data</span><span class="special">)</span> <span class="special">{</span> | |
5676 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">promise</span><span class="special"><</span> <span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">errorcode</span> <span class="special">></span> <span class="identifier">promise</span><span class="special">;</span> | |
5677 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">errorcode</span> <span class="special">></span> <span class="identifier">future</span><span class="special">(</span> <span class="identifier">promise</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">()</span> <span class="special">);</span> | |
5678 | <span class="comment">// In general, even though we block waiting for future::get() and therefore</span> | |
5679 | <span class="comment">// won't destroy 'promise' until promise::set_value() has been called, we</span> | |
5680 | <span class="comment">// are advised that with threads it's possible for ~promise() to be</span> | |
5681 | <span class="comment">// entered before promise::set_value() has returned. While that shouldn't</span> | |
5682 | <span class="comment">// happen with fibers::promise, a robust way to deal with the lifespan</span> | |
5683 | <span class="comment">// issue is to bind 'promise' into our lambda. Since promise is move-only,</span> | |
5684 | <span class="comment">// use initialization capture.</span> | |
5685 | <span class="identifier">api</span><span class="special">.</span><span class="identifier">init_write</span><span class="special">(</span> | |
5686 | <span class="identifier">data</span><span class="special">,</span> | |
5687 | <span class="special">[&</span><span class="identifier">promise</span><span class="special">](</span> <span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">errorcode</span> <span class="identifier">ec</span><span class="special">)</span> <span class="keyword">mutable</span> <span class="special">{</span> | |
5688 | <span class="identifier">promise</span><span class="special">.</span><span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">ec</span><span class="special">);</span> | |
5689 | <span class="special">});</span> | |
5690 | <span class="keyword">return</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span> | |
5691 | <span class="special">}</span> | |
5692 | </pre> | |
5693 | <p> | |
5694 | </p> | |
5695 | <p> | |
5696 | All we have to do is: | |
5697 | </p> | |
5698 | <div class="orderedlist"><ol class="orderedlist" type="1"> | |
5699 | <li class="listitem"> | |
5700 | Instantiate a <code class="computeroutput"><span class="identifier">promise</span><span class="special"><></span></code> of correct type. | |
5701 | </li> | |
5702 | <li class="listitem"> | |
5703 | Obtain its <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code>. | |
5704 | </li> | |
5705 | <li class="listitem"> | |
5706 | Arrange for the callback to call <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a>. | |
5707 | </li> | |
5708 | <li class="listitem"> | |
5709 | Block on <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a>. | |
5710 | </li> | |
5711 | </ol></div> | |
5712 | <div class="note"><table border="0" summary="Note"> | |
5713 | <tr> | |
5714 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> | |
5715 | <th align="left">Note</th> | |
5716 | </tr> | |
5717 | <tr><td align="left" valign="top"><p> | |
5718 | This tactic for resuming a pending fiber works even if the callback | |
5719 | is called on a different thread than the one on which the initiating | |
5720 | fiber is running. In fact, <a href="../../../../../examples/adapt_callbacks.cpp" target="_top">the | |
5721 | example program's</a> dummy <code class="computeroutput"><span class="identifier">AsyncAPI</span></code> | |
5722 | implementation illustrates that: it simulates async I/O by launching | |
5723 | a new thread that sleeps briefly and then calls the relevant callback. | |
5724 | </p></td></tr> | |
5725 | </table></div> | |
5726 | <h6> | |
5727 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.h2"></a> | |
5728 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.success_or_exception"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.success_or_exception">Success | |
5729 | or Exception</a> | |
5730 | </h6> | |
5731 | <p> | |
5732 | A wrapper more aligned with modern C++ practice would use an exception, | |
5733 | rather than an <code class="computeroutput"><span class="identifier">errorcode</span></code>, | |
5734 | to communicate failure to its caller. This is straightforward to code | |
5735 | in terms of <code class="computeroutput"><span class="identifier">write_ec</span><span class="special">()</span></code>: | |
5736 | </p> | |
5737 | <p> | |
5738 | </p> | |
5739 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">write</span><span class="special">(</span> <span class="identifier">AsyncAPI</span> <span class="special">&</span> <span class="identifier">api</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">data</span><span class="special">)</span> <span class="special">{</span> | |
5740 | <span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">errorcode</span> <span class="identifier">ec</span> <span class="special">=</span> <span class="identifier">write_ec</span><span class="special">(</span> <span class="identifier">api</span><span class="special">,</span> <span class="identifier">data</span><span class="special">);</span> | |
5741 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">{</span> | |
5742 | <span class="keyword">throw</span> <span class="identifier">make_exception</span><span class="special">(</span><span class="string">"write"</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">);</span> | |
5743 | <span class="special">}</span> | |
5744 | <span class="special">}</span> | |
5745 | </pre> | |
5746 | <p> | |
5747 | </p> | |
5748 | <p> | |
5749 | The point is that since each fiber has its own stack, you need not repeat | |
5750 | messy boilerplate: normal encapsulation works. | |
5751 | </p> | |
5752 | <h6> | |
5753 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.h3"></a> | |
5754 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.return_errorcode_or_data"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.return_errorcode_or_data">Return | |
5755 | Errorcode or Data</a> | |
5756 | </h6> | |
5757 | <p> | |
5758 | Things get a bit more interesting when the async operation's callback | |
5759 | passes multiple data items of interest. One approach would be to use | |
5760 | <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><></span></code> | |
5761 | to capture both: | |
5762 | </p> | |
5763 | <p> | |
5764 | </p> | |
5765 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span> <span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">errorcode</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">read_ec</span><span class="special">(</span> <span class="identifier">AsyncAPI</span> <span class="special">&</span> <span class="identifier">api</span><span class="special">)</span> <span class="special">{</span> | |
5766 | <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span> <span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">errorcode</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">result_pair</span><span class="special">;</span> | |
5767 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">promise</span><span class="special"><</span> <span class="identifier">result_pair</span> <span class="special">></span> <span class="identifier">promise</span><span class="special">;</span> | |
5768 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">result_pair</span> <span class="special">></span> <span class="identifier">future</span><span class="special">(</span> <span class="identifier">promise</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">()</span> <span class="special">);</span> | |
5769 | <span class="comment">// We promise that both 'promise' and 'future' will survive until our</span> | |
5770 | <span class="comment">// lambda has been called.</span> | |
5771 | <span class="identifier">api</span><span class="special">.</span><span class="identifier">init_read</span><span class="special">([&</span><span class="identifier">promise</span><span class="special">](</span> <span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">errorcode</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">data</span><span class="special">)</span> <span class="keyword">mutable</span> <span class="special">{</span> | |
5772 | <span class="identifier">promise</span><span class="special">.</span><span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">result_pair</span><span class="special">(</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">data</span><span class="special">)</span> <span class="special">);</span> | |
5773 | <span class="special">});</span> | |
5774 | <span class="keyword">return</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span> | |
5775 | <span class="special">}</span> | |
5776 | </pre> | |
5777 | <p> | |
5778 | </p> | |
5779 | <p> | |
5780 | Once you bundle the interesting data in <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><></span></code>, the code is effectively identical | |
5781 | to <code class="computeroutput"><span class="identifier">write_ec</span><span class="special">()</span></code>. | |
5782 | You can call it like this: | |
5783 | </p> | |
5784 | <p> | |
5785 | </p> | |
5786 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">tie</span><span class="special">(</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">data</span><span class="special">)</span> <span class="special">=</span> <span class="identifier">read_ec</span><span class="special">(</span> <span class="identifier">api</span><span class="special">);</span> | |
5787 | </pre> | |
5788 | <p> | |
5789 | </p> | |
5790 | <a name="Data_or_Exception"></a><h6> | |
5791 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.h4"></a> | |
5792 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.data_or_exception"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.data_or_exception">Data | |
5793 | or Exception</a> | |
5794 | </h6> | |
5795 | <p> | |
5796 | But a more natural API for a function that obtains data is to return | |
5797 | only the data on success, throwing an exception on error. | |
5798 | </p> | |
5799 | <p> | |
5800 | As with <code class="computeroutput"><span class="identifier">write</span><span class="special">()</span></code> | |
5801 | above, it's certainly possible to code a <code class="computeroutput"><span class="identifier">read</span><span class="special">()</span></code> wrapper in terms of <code class="computeroutput"><span class="identifier">read_ec</span><span class="special">()</span></code>. But since a given application is unlikely | |
5802 | to need both, let's code <code class="computeroutput"><span class="identifier">read</span><span class="special">()</span></code> from scratch, leveraging <a class="link" href="pooled_fixedsize.html#promise_set_exception"> <code class="computeroutput">promise::set_exception()</code></a>: | |
5803 | </p> | |
5804 | <p> | |
5805 | </p> | |
5806 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">read</span><span class="special">(</span> <span class="identifier">AsyncAPI</span> <span class="special">&</span> <span class="identifier">api</span><span class="special">)</span> <span class="special">{</span> | |
5807 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">promise</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">promise</span><span class="special">;</span> | |
5808 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">future</span><span class="special">(</span> <span class="identifier">promise</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">()</span> <span class="special">);</span> | |
5809 | <span class="comment">// Both 'promise' and 'future' will survive until our lambda has been</span> | |
5810 | <span class="comment">// called.</span> | |
5811 | <span class="identifier">api</span><span class="special">.</span><span class="identifier">init_read</span><span class="special">([&</span><span class="identifier">promise</span><span class="special">](</span> <span class="identifier">AsyncAPI</span><span class="special">::</span><span class="identifier">errorcode</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">data</span><span class="special">)</span> <span class="keyword">mutable</span> <span class="special">{</span> | |
5812 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">{</span> | |
5813 | <span class="identifier">promise</span><span class="special">.</span><span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">data</span><span class="special">);</span> | |
5814 | <span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span> | |
5815 | <span class="identifier">promise</span><span class="special">.</span><span class="identifier">set_exception</span><span class="special">(</span> | |
5816 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_exception_ptr</span><span class="special">(</span> | |
5817 | <span class="identifier">make_exception</span><span class="special">(</span><span class="string">"read"</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">)</span> <span class="special">);</span> | |
5818 | <span class="special">}</span> | |
5819 | <span class="special">});</span> | |
5820 | <span class="keyword">return</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span> | |
5821 | <span class="special">}</span> | |
5822 | </pre> | |
5823 | <p> | |
5824 | </p> | |
5825 | <p> | |
5826 | <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a> will do the right thing, either returning <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> or throwing an exception. | |
5827 | </p> | |
5828 | <h6> | |
5829 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.h5"></a> | |
5830 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.success_error_virtual_methods"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.success_error_virtual_methods">Success/Error | |
5831 | Virtual Methods</a> | |
5832 | </h6> | |
5833 | <p> | |
5834 | One classic approach to completion notification is to define an abstract | |
5835 | base class with <code class="computeroutput"><span class="identifier">success</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">error</span><span class="special">()</span></code> methods. Code wishing to perform async | |
5836 | I/O must derive a subclass, override each of these methods and pass the | |
5837 | async operation a pointer to a subclass instance. The abstract base class | |
5838 | might look like this: | |
5839 | </p> | |
5840 | <p> | |
5841 | </p> | |
5842 | <pre class="programlisting"><span class="comment">// every async operation receives a subclass instance of this abstract base</span> | |
5843 | <span class="comment">// class through which to communicate its result</span> | |
5844 | <span class="keyword">struct</span> <span class="identifier">Response</span> <span class="special">{</span> | |
5845 | <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">Response</span> <span class="special">></span> <span class="identifier">ptr</span><span class="special">;</span> | |
5846 | ||
5847 | <span class="comment">// called if the operation succeeds</span> | |
5848 | <span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">success</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">data</span><span class="special">)</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> | |
5849 | ||
5850 | <span class="comment">// called if the operation fails</span> | |
5851 | <span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">error</span><span class="special">(</span> <span class="identifier">AsyncAPIBase</span><span class="special">::</span><span class="identifier">errorcode</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> | |
5852 | <span class="special">};</span> | |
5853 | </pre> | |
5854 | <p> | |
5855 | </p> | |
5856 | <p> | |
5857 | Now the <code class="computeroutput"><span class="identifier">AsyncAPI</span></code> operation | |
5858 | might look more like this: | |
5859 | </p> | |
5860 | <p> | |
5861 | </p> | |
5862 | <pre class="programlisting"><span class="comment">// derive Response subclass, instantiate, pass Response::ptr</span> | |
5863 | <span class="keyword">void</span> <span class="identifier">init_read</span><span class="special">(</span> <span class="identifier">Response</span><span class="special">::</span><span class="identifier">ptr</span><span class="special">);</span> | |
5864 | </pre> | |
5865 | <p> | |
5866 | </p> | |
5867 | <p> | |
5868 | We can address this by writing a one-size-fits-all <code class="computeroutput"><span class="identifier">PromiseResponse</span></code>: | |
5869 | </p> | |
5870 | <p> | |
5871 | </p> | |
5872 | <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">PromiseResponse</span><span class="special">:</span> <span class="keyword">public</span> <span class="identifier">Response</span> <span class="special">{</span> | |
5873 | <span class="keyword">public</span><span class="special">:</span> | |
5874 | <span class="comment">// called if the operation succeeds</span> | |
5875 | <span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">success</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">data</span><span class="special">)</span> <span class="special">{</span> | |
5876 | <span class="identifier">promise_</span><span class="special">.</span><span class="identifier">set_value</span><span class="special">(</span> <span class="identifier">data</span><span class="special">);</span> | |
5877 | <span class="special">}</span> | |
5878 | ||
5879 | <span class="comment">// called if the operation fails</span> | |
5880 | <span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">error</span><span class="special">(</span> <span class="identifier">AsyncAPIBase</span><span class="special">::</span><span class="identifier">errorcode</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">{</span> | |
5881 | <span class="identifier">promise_</span><span class="special">.</span><span class="identifier">set_exception</span><span class="special">(</span> | |
5882 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_exception_ptr</span><span class="special">(</span> | |
5883 | <span class="identifier">make_exception</span><span class="special">(</span><span class="string">"read"</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">)</span> <span class="special">);</span> | |
5884 | <span class="special">}</span> | |
5885 | ||
5886 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">get_future</span><span class="special">()</span> <span class="special">{</span> | |
5887 | <span class="keyword">return</span> <span class="identifier">promise_</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">();</span> | |
5888 | <span class="special">}</span> | |
5889 | ||
5890 | <span class="keyword">private</span><span class="special">:</span> | |
5891 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">promise</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">promise_</span><span class="special">;</span> | |
5892 | <span class="special">};</span> | |
5893 | </pre> | |
5894 | <p> | |
5895 | </p> | |
5896 | <p> | |
5897 | Now we can simply obtain the <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> from that <code class="computeroutput"><span class="identifier">PromiseResponse</span></code> | |
5898 | and wait on its <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code>: | |
5899 | </p> | |
5900 | <p> | |
5901 | </p> | |
5902 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">read</span><span class="special">(</span> <span class="identifier">AsyncAPI</span> <span class="special">&</span> <span class="identifier">api</span><span class="special">)</span> <span class="special">{</span> | |
5903 | <span class="comment">// Because init_read() requires a shared_ptr, we must allocate our</span> | |
5904 | <span class="comment">// ResponsePromise on the heap, even though we know its lifespan.</span> | |
5905 | <span class="keyword">auto</span> <span class="identifier">promisep</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">PromiseResponse</span> <span class="special">>()</span> <span class="special">);</span> | |
5906 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">future</span><span class="special">(</span> <span class="identifier">promisep</span><span class="special">-></span><span class="identifier">get_future</span><span class="special">()</span> <span class="special">);</span> | |
5907 | <span class="comment">// Both 'promisep' and 'future' will survive until our lambda has been</span> | |
5908 | <span class="comment">// called.</span> | |
5909 | <span class="identifier">api</span><span class="special">.</span><span class="identifier">init_read</span><span class="special">(</span> <span class="identifier">promisep</span><span class="special">);</span> | |
5910 | <span class="keyword">return</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span> | |
5911 | <span class="special">}</span> | |
5912 | </pre> | |
5913 | <p> | |
5914 | </p> | |
5915 | <p> | |
5916 | The source code above is found in <a href="../../../../../examples/adapt_callbacks.cpp" target="_top">adapt_callbacks.cpp</a> | |
5917 | and <a href="../../../../../examples/adapt_method_calls.cpp" target="_top">adapt_method_calls.cpp</a>. | |
5918 | </p> | |
5919 | <a name="callbacks_asio"></a><h6> | |
5920 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.h6"></a> | |
5921 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.then_there_s__ulink_url__http___www_boost_org_doc_libs_release_libs_asio_index_html__boost_asio__ulink_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.then_there_s__ulink_url__http___www_boost_org_doc_libs_release_libs_asio_index_html__boost_asio__ulink_">Then | |
5922 | There's <a href="http://www.boost.org/doc/libs/release/libs/asio/index.html" target="_top">Boost.Asio</a></a> | |
5923 | </h6> | |
5924 | <p> | |
5925 | Since the simplest form of Boost.Asio asynchronous operation completion | |
5926 | token is a callback function, we could apply the same tactics for Asio | |
5927 | as for our hypothetical <code class="computeroutput"><span class="identifier">AsyncAPI</span></code> | |
5928 | asynchronous operations. | |
5929 | </p> | |
5930 | <p> | |
5931 | Fortunately we need not. Boost.Asio incorporates a mechanism<sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.f0" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.f0" class="footnote">5</a>]</sup> by which the caller can customize the notification behavior | |
5932 | of every async operation. Therefore we can construct a <span class="emphasis"><em>completion | |
5933 | token</em></span> which, when passed to a <a href="http://www.boost.org/doc/libs/release/libs/asio/index.html" target="_top">Boost.Asio</a> | |
5934 | async operation, requests blocking for the calling fiber. | |
5935 | </p> | |
5936 | <p> | |
5937 | A typical Asio async function might look something like this:<sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.f1" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.f1" class="footnote">6</a>]</sup> | |
5938 | </p> | |
5939 | <pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span> <span class="special">...,</span> <span class="keyword">class</span> <span class="identifier">CompletionToken</span> <span class="special">></span> | |
5940 | <span class="emphasis"><em>deduced_return_type</em></span> | |
5941 | <span class="identifier">async_something</span><span class="special">(</span> <span class="special">...</span> <span class="special">,</span> <span class="identifier">CompletionToken</span><span class="special">&&</span> <span class="identifier">token</span><span class="special">)</span> | |
5942 | <span class="special">{</span> | |
5943 | <span class="comment">// construct handler_type instance from CompletionToken</span> | |
5944 | <span class="identifier">handler_type</span><span class="special"><</span><span class="identifier">CompletionToken</span><span class="special">,</span> <span class="special">...>::</span><span class="identifier">type</span> <span class="identifier">handler</span><span class="special">(</span><span class="identifier">token</span><span class="special">);</span> | |
5945 | <span class="comment">// construct async_result instance from handler_type</span> | |
5946 | <span class="identifier">async_result</span><span class="special"><</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">handler</span><span class="special">)></span> <span class="identifier">result</span><span class="special">(</span><span class="identifier">handler</span><span class="special">);</span> | |
5947 | ||
5948 | <span class="comment">// ... arrange to call handler on completion ...</span> | |
5949 | <span class="comment">// ... initiate actual I/O operation ...</span> | |
5950 | ||
5951 | <span class="keyword">return</span> <span class="identifier">result</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span> | |
5952 | <span class="special">}</span> | |
5953 | </pre> | |
5954 | <p> | |
5955 | We will engage that mechanism, which is based on specializing Asio's | |
5956 | <code class="computeroutput"><span class="identifier">handler_type</span><span class="special"><></span></code> | |
5957 | template for the <code class="computeroutput"><span class="identifier">CompletionToken</span></code> | |
5958 | type and the signature of the specific callback. The remainder of this | |
5959 | discussion will refer back to <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> as the Asio async function under consideration. | |
5960 | </p> | |
5961 | <p> | |
5962 | The implementation described below uses lower-level facilities than | |
5963 | <code class="computeroutput"><span class="identifier">promise</span></code> and <code class="computeroutput"><span class="identifier">future</span></code> for two reasons: | |
5964 | </p> | |
5965 | <div class="orderedlist"><ol class="orderedlist" type="1"> | |
5966 | <li class="listitem"> | |
5967 | The <code class="computeroutput"><span class="identifier">promise</span></code> mechanism | |
5968 | interacts badly with <a href="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/stop.html" target="_top"><code class="computeroutput"><span class="identifier">io_service</span><span class="special">::</span><span class="identifier">stop</span><span class="special">()</span></code></a>. | |
5969 | It produces <code class="computeroutput"><span class="identifier">broken_promise</span></code> | |
5970 | exceptions. | |
5971 | </li> | |
5972 | <li class="listitem"> | |
5973 | If more than one thread is calling the <a href="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html" target="_top"><code class="computeroutput"><span class="identifier">io_service</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code></a> | |
5974 | method, the implementation described below allows resuming the suspended | |
5975 | fiber on whichever thread gets there first with completion notification. | |
5976 | ||
5977 | </li> | |
5978 | </ol></div> | |
5979 | <p> | |
5980 | <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">yield</span></code> is a completion token of this | |
5981 | kind. <code class="computeroutput"><span class="identifier">yield</span></code> is an instance | |
5982 | of <code class="computeroutput"><span class="identifier">yield_t</span></code>: | |
5983 | </p> | |
5984 | <p> | |
5985 | </p> | |
5986 | <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">yield_t</span> <span class="special">{</span> | |
5987 | <span class="keyword">public</span><span class="special">:</span> | |
5988 | <span class="identifier">yield_t</span><span class="special">(</span> <span class="keyword">bool</span> <span class="identifier">hop</span><span class="special">)</span> <span class="special">:</span> | |
5989 | <span class="identifier">allow_hop_</span><span class="special">(</span> <span class="identifier">hop</span><span class="special">)</span> <span class="special">{</span> | |
5990 | <span class="special">}</span> | |
5991 | ||
5992 | <span class="comment">/** | |
5993 | * @code | |
5994 | * static yield_t yield; | |
5995 | * boost::system::error_code myec; | |
5996 | * func(yield[myec]); | |
5997 | * @endcode | |
5998 | * @c yield[myec] returns an instance of @c yield_t whose @c ec_ points | |
5999 | * to @c myec. The expression @c yield[myec] "binds" @c myec to that | |
6000 | * (anonymous) @c yield_t instance, instructing @c func() to store any | |
6001 | * @c error_code it might produce into @c myec rather than throwing @c | |
6002 | * boost::system::system_error. | |
6003 | */</span> | |
6004 | <span class="identifier">yield_t</span> <span class="keyword">operator</span><span class="special">[](</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span> <span class="special">&</span> <span class="identifier">ec</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span> | |
6005 | <span class="identifier">yield_t</span> <span class="identifier">tmp</span><span class="special">{</span> <span class="special">*</span> <span class="keyword">this</span> <span class="special">};</span> | |
6006 | <span class="identifier">tmp</span><span class="special">.</span><span class="identifier">ec_</span> <span class="special">=</span> <span class="special">&</span> <span class="identifier">ec</span><span class="special">;</span> | |
6007 | <span class="keyword">return</span> <span class="identifier">tmp</span><span class="special">;</span> | |
6008 | <span class="special">}</span> | |
6009 | ||
6010 | <span class="comment">//private:</span> | |
6011 | <span class="comment">// ptr to bound error_code instance if any</span> | |
6012 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span> <span class="special">*</span> <span class="identifier">ec_</span><span class="special">{</span> <span class="keyword">nullptr</span> <span class="special">};</span> | |
6013 | <span class="comment">// allow calling fiber to "hop" to another thread if it could resume more</span> | |
6014 | <span class="comment">// quickly that way</span> | |
6015 | <span class="keyword">bool</span> <span class="identifier">allow_hop_</span><span class="special">;</span> | |
6016 | <span class="special">};</span> | |
6017 | </pre> | |
6018 | <p> | |
6019 | </p> | |
6020 | <p> | |
6021 | <code class="computeroutput"><span class="identifier">yield_t</span></code> is in fact only | |
6022 | a placeholder, a way to trigger Boost.Asio customization. It can bind | |
6023 | a <a href="http://www.boost.org/doc/libs/release/libs/system/doc/reference.html#Class-error_code" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span></code></a> for use by the actual | |
6024 | handler. | |
6025 | </p> | |
6026 | <p> | |
6027 | In fact there are two canonical instances of <code class="computeroutput"><span class="identifier">yield_t</span></code> | |
6028 | — <code class="computeroutput"><span class="identifier">yield</span></code> and <code class="computeroutput"><span class="identifier">yield_hop</span></code>: | |
6029 | </p> | |
6030 | <p> | |
6031 | </p> | |
6032 | <pre class="programlisting"><span class="comment">// canonical instance with allow_hop_ == false</span> | |
6033 | <span class="keyword">thread_local</span> <span class="identifier">yield_t</span> <span class="identifier">yield</span><span class="special">{</span> <span class="keyword">false</span> <span class="special">};</span> | |
6034 | <span class="comment">// canonical instance with allow_hop_ == true</span> | |
6035 | <span class="keyword">thread_local</span> <span class="identifier">yield_t</span> <span class="identifier">yield_hop</span><span class="special">{</span> <span class="keyword">true</span> <span class="special">};</span> | |
6036 | </pre> | |
6037 | <p> | |
6038 | </p> | |
6039 | <p> | |
6040 | We'll get to the differences between these shortly. | |
6041 | </p> | |
6042 | <p> | |
6043 | Asio customization is engaged by specializing <a href="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/handler_type.html" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">handler_type</span><span class="special"><></span></code></a> | |
6044 | for <code class="computeroutput"><span class="identifier">yield_t</span></code>: | |
6045 | </p> | |
6046 | <p> | |
6047 | </p> | |
6048 | <pre class="programlisting"><span class="comment">// Handler type specialisation for fibers::asio::yield.</span> | |
6049 | <span class="comment">// When 'yield' is passed as a completion handler which accepts only</span> | |
6050 | <span class="comment">// error_code, use yield_handler<void>. yield_handler will take care of the</span> | |
6051 | <span class="comment">// error_code one way or another.</span> | |
6052 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">ReturnType</span> <span class="special">></span> | |
6053 | <span class="keyword">struct</span> <span class="identifier">handler_type</span><span class="special"><</span> <span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">yield_t</span><span class="special">,</span> <span class="identifier">ReturnType</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">)</span> <span class="special">></span> | |
6054 | <span class="special">{</span> <span class="keyword">typedef</span> <span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">yield_handler</span><span class="special"><</span> <span class="keyword">void</span> <span class="special">></span> <span class="identifier">type</span><span class="special">;</span> <span class="special">};</span> | |
6055 | </pre> | |
6056 | <p> | |
6057 | </p> | |
6058 | <p> | |
6059 | (There are actually four different specializations in <a href="../../../../../examples/asio/detail/yield.hpp" target="_top">detail/yield.hpp</a>, | |
6060 | one for each of the four Asio async callback signatures we expect to | |
6061 | have to support.) | |
6062 | </p> | |
6063 | <p> | |
6064 | The above directs Asio to use <code class="computeroutput"><span class="identifier">yield_handler</span></code> | |
6065 | as the actual handler for an async operation to which <code class="computeroutput"><span class="identifier">yield</span></code> | |
6066 | is passed. There's a generic <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> implementation and a <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> | |
6067 | specialization. Let's start with the <code class="computeroutput"><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> | |
6068 | specialization: | |
6069 | </p> | |
6070 | <p> | |
6071 | </p> | |
6072 | <pre class="programlisting"><span class="comment">// yield_handler<void> is like yield_handler<T> without value_. In fact it's</span> | |
6073 | <span class="comment">// just like yield_handler_base.</span> | |
6074 | <span class="keyword">template</span><span class="special"><></span> | |
6075 | <span class="keyword">class</span> <span class="identifier">yield_handler</span><span class="special"><</span> <span class="keyword">void</span> <span class="special">>:</span> <span class="keyword">public</span> <span class="identifier">yield_handler_base</span> <span class="special">{</span> | |
6076 | <span class="keyword">public</span><span class="special">:</span> | |
6077 | <span class="keyword">explicit</span> <span class="identifier">yield_handler</span><span class="special">(</span> <span class="identifier">yield_t</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">:</span> | |
6078 | <span class="identifier">yield_handler_base</span><span class="special">{</span> <span class="identifier">y</span> <span class="special">}</span> <span class="special">{</span> | |
6079 | <span class="special">}</span> | |
6080 | ||
6081 | <span class="comment">// nullary completion callback</span> | |
6082 | <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()()</span> <span class="special">{</span> | |
6083 | <span class="special">(</span> <span class="special">*</span> <span class="keyword">this</span><span class="special">)(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">()</span> <span class="special">);</span> | |
6084 | <span class="special">}</span> | |
6085 | ||
6086 | <span class="comment">// inherit operator()(error_code) overload from base class</span> | |
6087 | <span class="keyword">using</span> <span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">();</span> | |
6088 | <span class="special">};</span> | |
6089 | </pre> | |
6090 | <p> | |
6091 | </p> | |
6092 | <p> | |
6093 | <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code>, | |
6094 | having consulted the <code class="computeroutput"><span class="identifier">handler_type</span><span class="special"><></span></code> traits specialization, instantiates | |
6095 | a <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> | |
6096 | to be passed as the actual callback for the async operation. <code class="computeroutput"><span class="identifier">yield_handler</span></code>'s constructor accepts | |
6097 | the <code class="computeroutput"><span class="identifier">yield_t</span></code> instance | |
6098 | (the <code class="computeroutput"><span class="identifier">yield</span></code> object passed | |
6099 | to the async function) and passes it along to <code class="computeroutput"><span class="identifier">yield_handler_base</span></code>: | |
6100 | </p> | |
6101 | <p> | |
6102 | </p> | |
6103 | <pre class="programlisting"><span class="comment">// This class encapsulates common elements between yield_handler<T> (capturing</span> | |
6104 | <span class="comment">// a value to return from asio async function) and yield_handler<void> (no</span> | |
6105 | <span class="comment">// such value). See yield_handler<T> and its <void> specialization below. Both</span> | |
6106 | <span class="comment">// yield_handler<T> and yield_handler<void> are passed by value through</span> | |
6107 | <span class="comment">// various layers of asio functions. In other words, they're potentially</span> | |
6108 | <span class="comment">// copied multiple times. So key data such as the yield_completion instance</span> | |
6109 | <span class="comment">// must be stored in our async_result<yield_handler<>> specialization, which</span> | |
6110 | <span class="comment">// should be instantiated only once.</span> | |
6111 | <span class="keyword">class</span> <span class="identifier">yield_handler_base</span> <span class="special">{</span> | |
6112 | <span class="keyword">public</span><span class="special">:</span> | |
6113 | <span class="identifier">yield_handler_base</span><span class="special">(</span> <span class="identifier">yield_t</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">:</span> | |
6114 | <span class="comment">// capture the context* associated with the running fiber</span> | |
6115 | <span class="identifier">ctx_</span><span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span><span class="special">::</span><span class="identifier">active</span><span class="special">()</span> <span class="special">},</span> | |
6116 | <span class="comment">// capture the passed yield_t</span> | |
6117 | <span class="identifier">yt_</span><span class="special">{</span> <span class="identifier">y</span> <span class="special">}</span> <span class="special">{</span> | |
6118 | <span class="special">}</span> | |
6119 | ||
6120 | <span class="comment">// completion callback passing only (error_code)</span> | |
6121 | <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">{</span> | |
6122 | <span class="identifier">BOOST_ASSERT_MSG</span><span class="special">(</span> <span class="identifier">ycomp_</span><span class="special">,</span> | |
6123 | <span class="string">"Must inject yield_completion* "</span> | |
6124 | <span class="string">"before calling yield_handler_base::operator()()"</span><span class="special">);</span> | |
6125 | <span class="identifier">BOOST_ASSERT_MSG</span><span class="special">(</span> <span class="identifier">yt_</span><span class="special">.</span><span class="identifier">ec_</span><span class="special">,</span> | |
6126 | <span class="string">"Must inject boost::system::error_code* "</span> | |
6127 | <span class="string">"before calling yield_handler_base::operator()()"</span><span class="special">);</span> | |
6128 | <span class="comment">// If originating fiber is busy testing completed_ flag, wait until it</span> | |
6129 | <span class="comment">// has observed (! completed_).</span> | |
6130 | <span class="identifier">yield_completion</span><span class="special">::</span><span class="identifier">lock_t</span> <span class="identifier">lk</span><span class="special">{</span> <span class="identifier">ycomp_</span><span class="special">-></span><span class="identifier">mtx_</span> <span class="special">};</span> | |
6131 | <span class="comment">// Notify a subsequent yield_completion::wait() call that it need not</span> | |
6132 | <span class="comment">// suspend.</span> | |
6133 | <span class="identifier">ycomp_</span><span class="special">-></span><span class="identifier">completed_</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span> | |
6134 | <span class="comment">// set the error_code bound by yield_t</span> | |
6135 | <span class="special">*</span> <span class="identifier">yt_</span><span class="special">.</span><span class="identifier">ec_</span> <span class="special">=</span> <span class="identifier">ec</span><span class="special">;</span> | |
6136 | <span class="comment">// Are we permitted to wake up the suspended fiber on this thread, the</span> | |
6137 | <span class="comment">// thread that called the completion handler?</span> | |
6138 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">ctx_</span><span class="special">-></span><span class="identifier">is_context</span><span class="special">(</span> <span class="identifier">fibers</span><span class="special">::</span><span class="identifier">type</span><span class="special">::</span><span class="identifier">pinned_context</span><span class="special">)</span> <span class="special">)</span> <span class="special">&&</span> <span class="identifier">yt_</span><span class="special">.</span><span class="identifier">allow_hop_</span><span class="special">)</span> <span class="special">{</span> | |
6139 | <span class="comment">// We must not migrate a pinned_context to another thread. If this</span> | |
6140 | <span class="comment">// isn't a pinned_context, and the application passed yield_hop</span> | |
6141 | <span class="comment">// rather than yield, migrate this fiber to the running thread.</span> | |
6142 | <span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span><span class="special">::</span><span class="identifier">active</span><span class="special">()-></span><span class="identifier">migrate</span><span class="special">(</span> <span class="identifier">ctx_</span><span class="special">);</span> | |
6143 | <span class="special">}</span> | |
6144 | <span class="comment">// either way, wake the fiber</span> | |
6145 | <span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span><span class="special">::</span><span class="identifier">active</span><span class="special">()-></span><span class="identifier">set_ready</span><span class="special">(</span> <span class="identifier">ctx_</span><span class="special">);</span> | |
6146 | <span class="special">}</span> | |
6147 | ||
6148 | <span class="comment">//private:</span> | |
6149 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">*</span> <span class="identifier">ctx_</span><span class="special">;</span> | |
6150 | <span class="identifier">yield_t</span> <span class="identifier">yt_</span><span class="special">;</span> | |
6151 | <span class="comment">// We depend on this pointer to yield_completion, which will be injected</span> | |
6152 | <span class="comment">// by async_result.</span> | |
6153 | <span class="identifier">yield_completion</span> <span class="special">*</span> <span class="identifier">ycomp_</span><span class="special">{</span> <span class="keyword">nullptr</span> <span class="special">};</span> | |
6154 | <span class="special">};</span> | |
6155 | </pre> | |
6156 | <p> | |
6157 | </p> | |
6158 | <p> | |
6159 | <code class="computeroutput"><span class="identifier">yield_handler_base</span></code> stores | |
6160 | a copy of the <code class="computeroutput"><span class="identifier">yield_t</span></code> | |
6161 | instance — which, as shown above, is only an <code class="computeroutput"><span class="identifier">error_code</span></code> | |
6162 | and a <code class="computeroutput"><span class="keyword">bool</span></code>. It also captures | |
6163 | the <a class="link" href="../../scheduling.html#class_context"> <code class="computeroutput">context</code></a>* for the currently-running fiber by calling | |
6164 | <a class="link" href="../../scheduling.html#context_active"> <code class="computeroutput">context::active()</code></a>. | |
6165 | </p> | |
6166 | <p> | |
6167 | You will notice that <code class="computeroutput"><span class="identifier">yield_handler_base</span></code> | |
6168 | has one more data member (<code class="computeroutput"><span class="identifier">ycomp_</span></code>) | |
6169 | that is initialized to <code class="computeroutput"><span class="keyword">nullptr</span></code> | |
6170 | by its constructor — though its <code class="computeroutput"><span class="keyword">operator</span><span class="special">()()</span></code> method relies on <code class="computeroutput"><span class="identifier">ycomp_</span></code> | |
6171 | being non-null. More on this in a moment. | |
6172 | </p> | |
6173 | <p> | |
6174 | Having constructed the <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> instance, <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> goes on to construct an <code class="computeroutput"><span class="identifier">async_result</span></code> specialized for the <code class="computeroutput"><span class="identifier">handler_type</span><span class="special"><>::</span><span class="identifier">type</span></code>: in this case, <code class="computeroutput"><span class="identifier">async_result</span><span class="special"><</span><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">>></span></code>. It passes the <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> | |
6175 | instance to the new <code class="computeroutput"><span class="identifier">async_result</span></code> | |
6176 | instance. | |
6177 | </p> | |
6178 | <p> | |
6179 | </p> | |
6180 | <pre class="programlisting"><span class="comment">// Without the need to handle a passed value, our yield_handler<void></span> | |
6181 | <span class="comment">// specialization is just like async_result_base.</span> | |
6182 | <span class="keyword">template</span><span class="special"><></span> | |
6183 | <span class="keyword">class</span> <span class="identifier">async_result</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">yield_handler</span><span class="special"><</span> <span class="keyword">void</span> <span class="special">></span> <span class="special">></span> <span class="special">:</span> | |
6184 | <span class="keyword">public</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">async_result_base</span> <span class="special">{</span> | |
6185 | <span class="keyword">public</span><span class="special">:</span> | |
6186 | <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">type</span><span class="special">;</span> | |
6187 | ||
6188 | <span class="keyword">explicit</span> <span class="identifier">async_result</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">yield_handler</span><span class="special"><</span> <span class="keyword">void</span> <span class="special">></span> <span class="special">&</span> <span class="identifier">h</span><span class="special">):</span> | |
6189 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">async_result_base</span><span class="special">{</span> <span class="identifier">h</span> <span class="special">}</span> <span class="special">{</span> | |
6190 | <span class="special">}</span> | |
6191 | <span class="special">};</span> | |
6192 | </pre> | |
6193 | <p> | |
6194 | </p> | |
6195 | <p> | |
6196 | Naturally that leads us straight to <code class="computeroutput"><span class="identifier">async_result_base</span></code>: | |
6197 | </p> | |
6198 | <p> | |
6199 | </p> | |
6200 | <pre class="programlisting"><span class="comment">// Factor out commonality between async_result<yield_handler<T>> and</span> | |
6201 | <span class="comment">// async_result<yield_handler<void>></span> | |
6202 | <span class="keyword">class</span> <span class="identifier">async_result_base</span> <span class="special">{</span> | |
6203 | <span class="keyword">public</span><span class="special">:</span> | |
6204 | <span class="keyword">explicit</span> <span class="identifier">async_result_base</span><span class="special">(</span> <span class="identifier">yield_handler_base</span> <span class="special">&</span> <span class="identifier">h</span><span class="special">)</span> <span class="special">{</span> | |
6205 | <span class="comment">// Inject ptr to our yield_completion instance into this</span> | |
6206 | <span class="comment">// yield_handler<>.</span> | |
6207 | <span class="identifier">h</span><span class="special">.</span><span class="identifier">ycomp_</span> <span class="special">=</span> <span class="special">&</span> <span class="keyword">this</span><span class="special">-></span><span class="identifier">ycomp_</span><span class="special">;</span> | |
6208 | <span class="comment">// if yield_t didn't bind an error_code, make yield_handler_base's</span> | |
6209 | <span class="comment">// error_code* point to an error_code local to this object so</span> | |
6210 | <span class="comment">// yield_handler_base::operator() can unconditionally store through</span> | |
6211 | <span class="comment">// its error_code*</span> | |
6212 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">h</span><span class="special">.</span><span class="identifier">yt_</span><span class="special">.</span><span class="identifier">ec_</span><span class="special">)</span> <span class="special">{</span> | |
6213 | <span class="identifier">h</span><span class="special">.</span><span class="identifier">yt_</span><span class="special">.</span><span class="identifier">ec_</span> <span class="special">=</span> <span class="special">&</span> <span class="identifier">ec_</span><span class="special">;</span> | |
6214 | <span class="special">}</span> | |
6215 | <span class="special">}</span> | |
6216 | ||
6217 | <span class="keyword">void</span> <span class="identifier">get</span><span class="special">()</span> <span class="special">{</span> | |
6218 | <span class="comment">// Unless yield_handler_base::operator() has already been called,</span> | |
6219 | <span class="comment">// suspend the calling fiber until that call.</span> | |
6220 | <span class="identifier">ycomp_</span><span class="special">.</span><span class="identifier">wait</span><span class="special">();</span> | |
6221 | <span class="comment">// The only way our own ec_ member could have a non-default value is</span> | |
6222 | <span class="comment">// if our yield_handler did not have a bound error_code AND the</span> | |
6223 | <span class="comment">// completion callback passed a non-default error_code.</span> | |
6224 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">ec_</span><span class="special">)</span> <span class="special">{</span> | |
6225 | <span class="identifier">throw_exception</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">system_error</span><span class="special">{</span> <span class="identifier">ec_</span> <span class="special">}</span> <span class="special">);</span> | |
6226 | <span class="special">}</span> | |
6227 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">interruption_point</span><span class="special">();</span> | |
6228 | <span class="special">}</span> | |
6229 | ||
6230 | <span class="keyword">private</span><span class="special">:</span> | |
6231 | <span class="comment">// If yield_t does not bind an error_code instance, store into here.</span> | |
6232 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span> <span class="identifier">ec_</span><span class="special">{};</span> | |
6233 | <span class="comment">// async_result_base owns the yield_completion because, unlike</span> | |
6234 | <span class="comment">// yield_handler<>, async_result<> is only instantiated once.</span> | |
6235 | <span class="identifier">yield_completion</span> <span class="identifier">ycomp_</span><span class="special">{};</span> | |
6236 | <span class="special">};</span> | |
6237 | </pre> | |
6238 | <p> | |
6239 | </p> | |
6240 | <p> | |
6241 | This is how <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="identifier">ycomp_</span></code> | |
6242 | becomes non-null: <code class="computeroutput"><span class="identifier">async_result_base</span></code>'s | |
6243 | constructor injects a pointer back to its own <code class="computeroutput"><span class="identifier">yield_completion</span></code> | |
6244 | member. | |
6245 | </p> | |
6246 | <p> | |
6247 | Recall that both of the canonical <code class="computeroutput"><span class="identifier">yield_t</span></code> | |
6248 | instances <code class="computeroutput"><span class="identifier">yield</span></code> and | |
6249 | <code class="computeroutput"><span class="identifier">yield_hop</span></code> initialize | |
6250 | their <code class="computeroutput"><span class="identifier">error_code</span><span class="special">*</span></code> | |
6251 | member <code class="computeroutput"><span class="identifier">ec_</span></code> to <code class="computeroutput"><span class="keyword">nullptr</span></code>. If either of these instances | |
6252 | is passed to <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> (<code class="computeroutput"><span class="identifier">ec_</span></code> | |
6253 | is still <code class="computeroutput"><span class="keyword">nullptr</span></code>), the copy | |
6254 | stored in <code class="computeroutput"><span class="identifier">yield_handler_base</span></code> | |
6255 | will likewise have null <code class="computeroutput"><span class="identifier">ec_</span></code>. | |
6256 | <code class="computeroutput"><span class="identifier">async_result_base</span></code>'s constructor | |
6257 | sets <code class="computeroutput"><span class="identifier">yield_handler_base</span></code>'s | |
6258 | <code class="computeroutput"><span class="identifier">yield_t</span></code>'s <code class="computeroutput"><span class="identifier">ec_</span></code> member to point to its own <code class="computeroutput"><span class="identifier">error_code</span></code> member. | |
6259 | </p> | |
6260 | <p> | |
6261 | The stage is now set. <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> initiates the actual async operation, | |
6262 | arranging to call its <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> instance on completion. Let's say, | |
6263 | for the sake of argument, that the actual async operation's callback | |
6264 | has signature <code class="computeroutput"><span class="keyword">void</span><span class="special">(</span><span class="identifier">error_code</span><span class="special">)</span></code>. | |
6265 | </p> | |
6266 | <p> | |
6267 | But since it's an async operation, control returns at once to <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code>. | |
6268 | <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> | |
6269 | calls <code class="computeroutput"><span class="identifier">async_result</span><span class="special"><</span><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">>>::</span><span class="identifier">get</span><span class="special">()</span></code>, | |
6270 | and will return its return value. | |
6271 | </p> | |
6272 | <p> | |
6273 | <code class="computeroutput"><span class="identifier">async_result</span><span class="special"><</span><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">>>::</span><span class="identifier">get</span><span class="special">()</span></code> | |
6274 | inherits <code class="computeroutput"><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">get</span><span class="special">()</span></code>. | |
6275 | </p> | |
6276 | <p> | |
6277 | <code class="computeroutput"><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">get</span><span class="special">()</span></code> | |
6278 | immediately calls <code class="computeroutput"><span class="identifier">yield_completion</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code>. | |
6279 | </p> | |
6280 | <p> | |
6281 | </p> | |
6282 | <pre class="programlisting"><span class="comment">// Bundle a completion bool flag with a spinlock to protect it.</span> | |
6283 | <span class="keyword">struct</span> <span class="identifier">yield_completion</span> <span class="special">{</span> | |
6284 | <span class="keyword">typedef</span> <span class="identifier">fibers</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">spinlock</span> <span class="identifier">mutex_t</span><span class="special">;</span> | |
6285 | <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special"><</span> <span class="identifier">mutex_t</span> <span class="special">></span> <span class="identifier">lock_t</span><span class="special">;</span> | |
6286 | ||
6287 | <span class="identifier">mutex_t</span> <span class="identifier">mtx_</span><span class="special">{};</span> | |
6288 | <span class="keyword">bool</span> <span class="identifier">completed_</span><span class="special">{</span> <span class="keyword">false</span> <span class="special">};</span> | |
6289 | ||
6290 | <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">()</span> <span class="special">{</span> | |
6291 | <span class="comment">// yield_handler_base::operator()() will set completed_ true and</span> | |
6292 | <span class="comment">// attempt to wake a suspended fiber. It would be Bad if that call</span> | |
6293 | <span class="comment">// happened between our detecting (! completed_) and suspending.</span> | |
6294 | <span class="identifier">lock_t</span> <span class="identifier">lk</span><span class="special">{</span> <span class="identifier">mtx_</span> <span class="special">};</span> | |
6295 | <span class="comment">// If completed_ is already set, we're done here: don't suspend.</span> | |
6296 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">completed_</span><span class="special">)</span> <span class="special">{</span> | |
6297 | <span class="comment">// suspend(unique_lock<spinlock>) unlocks the lock in the act of</span> | |
6298 | <span class="comment">// resuming another fiber</span> | |
6299 | <span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span><span class="special">::</span><span class="identifier">active</span><span class="special">()-></span><span class="identifier">suspend</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">);</span> | |
6300 | <span class="special">}</span> | |
6301 | <span class="special">}</span> | |
6302 | <span class="special">};</span> | |
6303 | </pre> | |
6304 | <p> | |
6305 | </p> | |
6306 | <p> | |
6307 | Supposing that the pending async operation has not yet completed, <code class="computeroutput"><span class="identifier">yield_completion</span><span class="special">::</span><span class="identifier">completed_</span></code> will still be <code class="computeroutput"><span class="keyword">false</span></code>, and <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> will call <a class="link" href="../../scheduling.html#context_suspend"> <code class="computeroutput">context::suspend()</code></a> on | |
6308 | the currently-running fiber. | |
6309 | </p> | |
6310 | <p> | |
6311 | Other fibers will now have a chance to run. | |
6312 | </p> | |
6313 | <p> | |
6314 | Some time later, the async operation completes. It calls <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">()(</span><span class="identifier">error_code</span> <span class="keyword">const</span><span class="special">&)</span></code> with an <code class="computeroutput"><span class="identifier">error_code</span></code> | |
6315 | indicating either success or failure. We'll consider both cases. | |
6316 | </p> | |
6317 | <p> | |
6318 | <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> | |
6319 | explicitly inherits <code class="computeroutput"><span class="keyword">operator</span><span class="special">()(</span><span class="identifier">error_code</span> | |
6320 | <span class="keyword">const</span><span class="special">&)</span></code> | |
6321 | from <code class="computeroutput"><span class="identifier">yield_handler_base</span></code>. | |
6322 | </p> | |
6323 | <p> | |
6324 | <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()(</span><span class="identifier">error_code</span> <span class="keyword">const</span><span class="special">&)</span></code> first sets <code class="computeroutput"><span class="identifier">yield_completion</span><span class="special">::</span><span class="identifier">completed_</span></code> | |
6325 | <code class="computeroutput"><span class="keyword">true</span></code>. This way, if <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code>'s | |
6326 | async operation completes immediately — if <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></code> is called even before <code class="computeroutput"><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">get</span><span class="special">()</span></code> | |
6327 | — the calling fiber will <span class="emphasis"><em>not</em></span> suspend. | |
6328 | </p> | |
6329 | <p> | |
6330 | The actual <code class="computeroutput"><span class="identifier">error_code</span></code> | |
6331 | produced by the async operation is then stored through the stored <code class="computeroutput"><span class="identifier">yield_t</span><span class="special">::</span><span class="identifier">ec_</span></code> pointer. If <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code>'s caller used (e.g.) <code class="computeroutput"><span class="identifier">yield</span><span class="special">[</span><span class="identifier">my_ec</span><span class="special">]</span></code> | |
6332 | to bind a local <code class="computeroutput"><span class="identifier">error_code</span></code> | |
6333 | instance, the actual <code class="computeroutput"><span class="identifier">error_code</span></code> | |
6334 | value is stored into the caller's variable. Otherwise, it is stored into | |
6335 | <code class="computeroutput"><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">ec_</span></code>. | |
6336 | </p> | |
6337 | <p> | |
6338 | Finally we get to the distinction between <code class="computeroutput"><span class="identifier">yield</span></code> | |
6339 | and <code class="computeroutput"><span class="identifier">yield_hop</span></code>. | |
6340 | </p> | |
6341 | <p> | |
6342 | As described for <a class="link" href="../../scheduling.html#context_is_context"> <code class="computeroutput">context::is_context()</code></a>, a <code class="computeroutput"><span class="identifier">pinned_context</span></code> fiber is special to | |
6343 | the library and must never be passed to <a class="link" href="../../scheduling.html#context_migrate"> <code class="computeroutput">context::migrate()</code></a>. | |
6344 | We must detect and avoid that case here. | |
6345 | </p> | |
6346 | <p> | |
6347 | The <code class="computeroutput"><span class="identifier">yield_t</span><span class="special">::</span><span class="identifier">allow_hop_</span></code> <code class="computeroutput"><span class="keyword">bool</span></code> | |
6348 | indicates whether <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code>'s caller is willing to allow the running | |
6349 | fiber to <span class="quote">“<span class="quote">hop</span>”</span> to another thread (<code class="computeroutput"><span class="identifier">yield_hop</span></code>) | |
6350 | or whether s/he insists that the fiber resume on the same thread (<code class="computeroutput"><span class="identifier">yield</span></code>). | |
6351 | </p> | |
6352 | <p> | |
6353 | If the caller passed <code class="computeroutput"><span class="identifier">yield_hop</span></code> | |
6354 | to <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code>, | |
6355 | and the running fiber isn't a <code class="computeroutput"><span class="identifier">pinned_context</span></code>, | |
6356 | <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></code> | |
6357 | passes the <code class="computeroutput"><span class="identifier">context</span></code> of | |
6358 | the original fiber — the one on which <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> was called, captured in <code class="computeroutput"><span class="identifier">yield_handler_base</span></code>'s constructor — to | |
6359 | the current thread's <a class="link" href="../../scheduling.html#context_migrate"> <code class="computeroutput">context::migrate()</code></a>. | |
6360 | </p> | |
6361 | <p> | |
6362 | If the running application has more than one thread calling <a href="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html" target="_top"><code class="computeroutput"><span class="identifier">io_service</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code></a>, | |
6363 | that fiber could return from <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> on a different thread (the one calling | |
6364 | <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></code>) | |
6365 | than the one on which it entered <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code>. | |
6366 | </p> | |
6367 | <p> | |
6368 | In any case, the fiber is marked as ready to run by passing it to <a class="link" href="../../scheduling.html#context_set_ready"> <code class="computeroutput">context::set_ready()</code></a>. | |
6369 | Control then returns from <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></code>: the callback is done. | |
6370 | </p> | |
6371 | <p> | |
6372 | In due course, the fiber <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="identifier">ctx_</span></code> | |
6373 | is resumed. Control returns from <a class="link" href="../../scheduling.html#context_suspend"> <code class="computeroutput">context::suspend()</code></a> to | |
6374 | <code class="computeroutput"><span class="identifier">yield_completion</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code>, | |
6375 | which returns to <code class="computeroutput"><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">get</span><span class="special">()</span></code>. | |
6376 | </p> | |
6377 | <div class="itemizedlist"><ul class="itemizedlist" type="disc"> | |
6378 | <li class="listitem"> | |
6379 | If the original caller passed <code class="computeroutput"><span class="identifier">yield</span><span class="special">[</span><span class="identifier">my_ec</span><span class="special">]</span></code> to <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> to bind a local <code class="computeroutput"><span class="identifier">error_code</span></code> | |
6380 | instance, then <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></code> stored its <code class="computeroutput"><span class="identifier">error_code</span></code> | |
6381 | to the caller's <code class="computeroutput"><span class="identifier">my_ec</span></code> | |
6382 | instance, leaving <code class="computeroutput"><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">ec_</span></code> | |
6383 | initialized to success. | |
6384 | </li> | |
6385 | <li class="listitem"> | |
6386 | If the original caller passed <code class="computeroutput"><span class="identifier">yield</span></code> | |
6387 | to <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> without binding a local <code class="computeroutput"><span class="identifier">error_code</span></code> variable, then <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></code> | |
6388 | stored its <code class="computeroutput"><span class="identifier">error_code</span></code> | |
6389 | into <code class="computeroutput"><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">ec_</span></code>. | |
6390 | If in fact that <code class="computeroutput"><span class="identifier">error_code</span></code> | |
6391 | is success, then all is well. | |
6392 | </li> | |
6393 | <li class="listitem"> | |
6394 | Otherwise — the original caller did not bind a local <code class="computeroutput"><span class="identifier">error_code</span></code> and <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></code> was called with an <code class="computeroutput"><span class="identifier">error_code</span></code> indicating error — <code class="computeroutput"><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">get</span><span class="special">()</span></code> | |
6395 | throws <code class="computeroutput"><span class="identifier">system_error</span></code> | |
6396 | with that <code class="computeroutput"><span class="identifier">error_code</span></code>. | |
6397 | </li> | |
6398 | </ul></div> | |
6399 | <p> | |
6400 | The case in which <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code>'s completion callback has signature | |
6401 | <code class="computeroutput"><span class="keyword">void</span><span class="special">()</span></code> | |
6402 | is similar. <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="keyword">void</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">()()</span></code> invokes the machinery above with | |
6403 | a <span class="quote">“<span class="quote">success</span>”</span> <code class="computeroutput"><span class="identifier">error_code</span></code>. | |
6404 | </p> | |
6405 | <p> | |
6406 | A completion callback with signature <code class="computeroutput"><span class="keyword">void</span><span class="special">(</span><span class="identifier">error_code</span><span class="special">,</span> <span class="identifier">T</span><span class="special">)</span></code> (that is: in addition to <code class="computeroutput"><span class="identifier">error_code</span></code>, callback receives some | |
6407 | data item) is handled somewhat differently. For this kind of signature, | |
6408 | <code class="computeroutput"><span class="identifier">handler_type</span><span class="special"><>::</span><span class="identifier">type</span></code> specifies <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> (for <code class="computeroutput"><span class="identifier">T</span></code> | |
6409 | other than <code class="computeroutput"><span class="keyword">void</span></code>). | |
6410 | </p> | |
6411 | <p> | |
6412 | A <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> | |
6413 | reserves a <code class="computeroutput"><span class="identifier">value_</span></code> pointer | |
6414 | to a value of type <code class="computeroutput"><span class="identifier">T</span></code>: | |
6415 | </p> | |
6416 | <p> | |
6417 | </p> | |
6418 | <pre class="programlisting"><span class="comment">// asio uses handler_type<completion token type, signature>::type to decide</span> | |
6419 | <span class="comment">// what to instantiate as the actual handler. Below, we specialize</span> | |
6420 | <span class="comment">// handler_type< yield_t, ... > to indicate yield_handler<>. So when you pass</span> | |
6421 | <span class="comment">// an instance of yield_t as an asio completion token, asio selects</span> | |
6422 | <span class="comment">// yield_handler<> as the actual handler class.</span> | |
6423 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">></span> | |
6424 | <span class="keyword">class</span> <span class="identifier">yield_handler</span><span class="special">:</span> <span class="keyword">public</span> <span class="identifier">yield_handler_base</span> <span class="special">{</span> | |
6425 | <span class="keyword">public</span><span class="special">:</span> | |
6426 | <span class="comment">// asio passes the completion token to the handler constructor</span> | |
6427 | <span class="keyword">explicit</span> <span class="identifier">yield_handler</span><span class="special">(</span> <span class="identifier">yield_t</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">:</span> | |
6428 | <span class="identifier">yield_handler_base</span><span class="special">{</span> <span class="identifier">y</span> <span class="special">}</span> <span class="special">{</span> | |
6429 | <span class="special">}</span> | |
6430 | ||
6431 | <span class="comment">// completion callback passing only value (T)</span> | |
6432 | <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span> <span class="identifier">T</span> <span class="identifier">t</span><span class="special">)</span> <span class="special">{</span> | |
6433 | <span class="comment">// just like callback passing success error_code</span> | |
6434 | <span class="special">(*</span><span class="keyword">this</span><span class="special">)(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">(),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">t</span><span class="special">)</span> <span class="special">);</span> | |
6435 | <span class="special">}</span> | |
6436 | ||
6437 | <span class="comment">// completion callback passing (error_code, T)</span> | |
6438 | <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">T</span> <span class="identifier">t</span><span class="special">)</span> <span class="special">{</span> | |
6439 | <span class="identifier">BOOST_ASSERT_MSG</span><span class="special">(</span> <span class="identifier">value_</span><span class="special">,</span> | |
6440 | <span class="string">"Must inject value ptr "</span> | |
6441 | <span class="string">"before caling yield_handler<T>::operator()()"</span><span class="special">);</span> | |
6442 | <span class="comment">// move the value to async_result<> instance BEFORE waking up a</span> | |
6443 | <span class="comment">// suspended fiber</span> | |
6444 | <span class="special">*</span> <span class="identifier">value_</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span> <span class="identifier">t</span><span class="special">);</span> | |
6445 | <span class="comment">// forward the call to base-class completion handler</span> | |
6446 | <span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()(</span> <span class="identifier">ec</span><span class="special">);</span> | |
6447 | <span class="special">}</span> | |
6448 | ||
6449 | <span class="comment">//private:</span> | |
6450 | <span class="comment">// pointer to destination for eventual value</span> | |
6451 | <span class="comment">// this must be injected by async_result before operator()() is called</span> | |
6452 | <span class="identifier">T</span> <span class="special">*</span> <span class="identifier">value_</span><span class="special">{</span> <span class="keyword">nullptr</span> <span class="special">};</span> | |
6453 | <span class="special">};</span> | |
6454 | </pre> | |
6455 | <p> | |
6456 | </p> | |
6457 | <p> | |
6458 | This pointer is initialized to <code class="computeroutput"><span class="keyword">nullptr</span></code>. | |
6459 | </p> | |
6460 | <p> | |
6461 | When <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> instantiates <code class="computeroutput"><span class="identifier">async_result</span><span class="special"><</span><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">>></span></code>: | |
6462 | </p> | |
6463 | <p> | |
6464 | </p> | |
6465 | <pre class="programlisting"><span class="comment">// asio constructs an async_result<> instance from the yield_handler specified</span> | |
6466 | <span class="comment">// by handler_type<>::type. A particular asio async method constructs the</span> | |
6467 | <span class="comment">// yield_handler, constructs this async_result specialization from it, then</span> | |
6468 | <span class="comment">// returns the result of calling its get() method.</span> | |
6469 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">></span> | |
6470 | <span class="keyword">class</span> <span class="identifier">async_result</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">yield_handler</span><span class="special"><</span> <span class="identifier">T</span> <span class="special">></span> <span class="special">></span> <span class="special">:</span> | |
6471 | <span class="keyword">public</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">async_result_base</span> <span class="special">{</span> | |
6472 | <span class="keyword">public</span><span class="special">:</span> | |
6473 | <span class="comment">// type returned by get()</span> | |
6474 | <span class="keyword">typedef</span> <span class="identifier">T</span> <span class="identifier">type</span><span class="special">;</span> | |
6475 | ||
6476 | <span class="keyword">explicit</span> <span class="identifier">async_result</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">yield_handler</span><span class="special"><</span> <span class="identifier">T</span> <span class="special">></span> <span class="special">&</span> <span class="identifier">h</span><span class="special">)</span> <span class="special">:</span> | |
6477 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">async_result_base</span><span class="special">{</span> <span class="identifier">h</span> <span class="special">}</span> <span class="special">{</span> | |
6478 | <span class="comment">// Inject ptr to our value_ member into yield_handler<>: result will</span> | |
6479 | <span class="comment">// be stored here.</span> | |
6480 | <span class="identifier">h</span><span class="special">.</span><span class="identifier">value_</span> <span class="special">=</span> <span class="special">&</span> <span class="identifier">value_</span><span class="special">;</span> | |
6481 | <span class="special">}</span> | |
6482 | ||
6483 | <span class="comment">// asio async method returns result of calling get()</span> | |
6484 | <span class="identifier">type</span> <span class="identifier">get</span><span class="special">()</span> <span class="special">{</span> | |
6485 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">detail</span><span class="special">::</span><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">get</span><span class="special">();</span> | |
6486 | <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span> <span class="identifier">value_</span><span class="special">);</span> | |
6487 | <span class="special">}</span> | |
6488 | ||
6489 | <span class="keyword">private</span><span class="special">:</span> | |
6490 | <span class="identifier">type</span> <span class="identifier">value_</span><span class="special">{};</span> | |
6491 | <span class="special">};</span> | |
6492 | </pre> | |
6493 | <p> | |
6494 | </p> | |
6495 | <p> | |
6496 | this <code class="computeroutput"><span class="identifier">async_result</span><span class="special"><></span></code> | |
6497 | specialization reserves a member of type <code class="computeroutput"><span class="identifier">T</span></code> | |
6498 | to receive the passed data item, and sets <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">value_</span></code> | |
6499 | to point to its own data member. | |
6500 | </p> | |
6501 | <p> | |
6502 | <code class="computeroutput"><span class="identifier">async_result</span><span class="special"><</span><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">>></span></code> | |
6503 | overrides <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code>. | |
6504 | The override calls <code class="computeroutput"><span class="identifier">async_result_base</span><span class="special">::</span><span class="identifier">get</span><span class="special">()</span></code>, so the calling fiber suspends as described | |
6505 | above. | |
6506 | </p> | |
6507 | <p> | |
6508 | <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">()(</span><span class="identifier">error_code</span><span class="special">,</span> | |
6509 | <span class="identifier">T</span><span class="special">)</span></code> | |
6510 | stores its passed <code class="computeroutput"><span class="identifier">T</span></code> value | |
6511 | into <code class="computeroutput"><span class="identifier">async_result</span><span class="special"><</span><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">>>::</span><span class="identifier">value_</span></code>. | |
6512 | </p> | |
6513 | <p> | |
6514 | Then it passes control to <code class="computeroutput"><span class="identifier">yield_handler_base</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()(</span><span class="identifier">error_code</span><span class="special">)</span></code> to deal with waking (and possibly migrating) | |
6515 | the original fiber as described above. | |
6516 | </p> | |
6517 | <p> | |
6518 | When <code class="computeroutput"><span class="identifier">async_result</span><span class="special"><</span><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">>>::</span><span class="identifier">get</span><span class="special">()</span></code> | |
6519 | resumes, it returns the stored <code class="computeroutput"><span class="identifier">value_</span></code> | |
6520 | to <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code> | |
6521 | and ultimately to <code class="computeroutput"><span class="identifier">async_something</span><span class="special">()</span></code>'s caller. | |
6522 | </p> | |
6523 | <p> | |
6524 | The case of a callback signature <code class="computeroutput"><span class="keyword">void</span><span class="special">(</span><span class="identifier">T</span><span class="special">)</span></code> is handled by having <code class="computeroutput"><span class="identifier">yield_handler</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T</span><span class="special">)</span></code> engage the <code class="computeroutput"><span class="keyword">void</span><span class="special">(</span><span class="identifier">error_code</span><span class="special">,</span> <span class="identifier">T</span><span class="special">)</span></code> machinery, passing a <span class="quote">“<span class="quote">success</span>”</span> | |
6525 | <code class="computeroutput"><span class="identifier">error_code</span></code>. | |
6526 | </p> | |
6527 | <p> | |
6528 | The source code above is found in <a href="../../../../../examples/asio/yield.hpp" target="_top">yield.hpp</a> | |
6529 | and <a href="../../../../../examples/asio/detail/yield.hpp" target="_top">detail/yield.hpp</a>. | |
6530 | </p> | |
6531 | </div> | |
6532 | <div class="section"> | |
6533 | <div class="titlepage"><div><div><h5 class="title"> | |
6534 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking"></a><a name="nonblocking"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking" title="Integrating Fibers with Nonblocking I/O">Integrating | |
6535 | Fibers with Nonblocking I/O</a> | |
6536 | </h5></div></div></div> | |
6537 | <h6> | |
6538 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.h0"></a> | |
6539 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.overview"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.overview">Overview</a> | |
6540 | </h6> | |
6541 | <p> | |
6542 | <span class="emphasis"><em>Nonblocking</em></span> I/O is distinct from <span class="emphasis"><em>asynchronous</em></span> | |
6543 | I/O. A true async I/O operation promises to initiate the operation and | |
6544 | notify the caller on completion, usually via some sort of callback (as | |
6545 | described in <a class="link" href="pooled_fixedsize.html#callbacks">Integrating Fibers with Asynchronous | |
6546 | Callbacks</a>). | |
6547 | </p> | |
6548 | <p> | |
6549 | In contrast, a nonblocking I/O operation refuses to start at all if it | |
6550 | would be necessary to block, returning an error code such as <a href="http://man7.org/linux/man-pages/man3/errno.3.html" target="_top"><code class="computeroutput"><span class="identifier">EWOULDBLOCK</span></code></a>. The operation | |
6551 | is performed only when it can complete immediately. In effect, the caller | |
6552 | must repeatedly retry the operation until it stops returning <code class="computeroutput"><span class="identifier">EWOULDBLOCK</span></code>. | |
6553 | </p> | |
6554 | <p> | |
6555 | In a classic event-driven program, it can be something of a headache | |
6556 | to use nonblocking I/O. At the point where the nonblocking I/O is attempted, | |
6557 | a return value of <code class="computeroutput"><span class="identifier">EWOULDBLOCK</span></code> | |
6558 | requires the caller to pass control back to the main event loop, arranging | |
6559 | to retry again on the next iteration. | |
6560 | </p> | |
6561 | <p> | |
6562 | Worse, a nonblocking I/O operation might <span class="emphasis"><em>partially</em></span> | |
6563 | succeed. That means that the relevant business logic must continue receiving | |
6564 | control on every main loop iteration until all required data have been | |
6565 | processed: a doubly-nested loop, implemented as a callback-driven state | |
6566 | machine. | |
6567 | </p> | |
6568 | <p> | |
6569 | <span class="bold"><strong>Boost.Fiber</strong></span> can simplify this problem | |
6570 | immensely. Once you have integrated with the application's main loop | |
6571 | as described in <a class="link" href="pooled_fixedsize.html#integration">Sharing a Thread with Another | |
6572 | Main Loop</a>, waiting for the next main-loop iteration is as simple | |
6573 | as calling <a class="link" href="../../fiber_mgmt/this_fiber.html#this_fiber_yield"> <code class="computeroutput">this_fiber::yield()</code></a>. | |
6574 | </p> | |
6575 | <h6> | |
6576 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.h1"></a> | |
6577 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.example_nonblocking_api"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.example_nonblocking_api">Example | |
6578 | Nonblocking API</a> | |
6579 | </h6> | |
6580 | <p> | |
6581 | For purposes of illustration, consider this API: | |
6582 | </p> | |
6583 | <p> | |
6584 | </p> | |
6585 | <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">NonblockingAPI</span> <span class="special">{</span> | |
6586 | <span class="keyword">public</span><span class="special">:</span> | |
6587 | <span class="identifier">NonblockingAPI</span><span class="special">();</span> | |
6588 | ||
6589 | <span class="comment">// nonblocking operation: may return EWOULDBLOCK</span> | |
6590 | <span class="keyword">int</span> <span class="identifier">read</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&</span> <span class="identifier">data</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">desired</span><span class="special">);</span> | |
6591 | ||
6592 | <span class="special">...</span> | |
6593 | <span class="special">};</span> | |
6594 | </pre> | |
6595 | <p> | |
6596 | </p> | |
6597 | <h6> | |
6598 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.h2"></a> | |
6599 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.polling_for_completion"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.polling_for_completion">Polling | |
6600 | for Completion</a> | |
6601 | </h6> | |
6602 | <p> | |
6603 | We can build a low-level wrapper around <code class="computeroutput"><span class="identifier">NonblockingAPI</span><span class="special">::</span><span class="identifier">read</span><span class="special">()</span></code> that shields its caller from ever having | |
6604 | to deal with <code class="computeroutput"><span class="identifier">EWOULDBLOCK</span></code>: | |
6605 | </p> | |
6606 | <p> | |
6607 | </p> | |
6608 | <pre class="programlisting"><span class="comment">// guaranteed not to return EWOULDBLOCK</span> | |
6609 | <span class="keyword">int</span> <span class="identifier">read_chunk</span><span class="special">(</span> <span class="identifier">NonblockingAPI</span> <span class="special">&</span> <span class="identifier">api</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&</span> <span class="identifier">data</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">desired</span><span class="special">)</span> <span class="special">{</span> | |
6610 | <span class="keyword">int</span> <span class="identifier">error</span><span class="special">;</span> | |
6611 | <span class="keyword">while</span> <span class="special">(</span> <span class="identifier">EWOULDBLOCK</span> <span class="special">==</span> <span class="special">(</span> <span class="identifier">error</span> <span class="special">=</span> <span class="identifier">api</span><span class="special">.</span><span class="identifier">read</span><span class="special">(</span> <span class="identifier">data</span><span class="special">,</span> <span class="identifier">desired</span><span class="special">)</span> <span class="special">)</span> <span class="special">)</span> <span class="special">{</span> | |
6612 | <span class="comment">// not ready yet -- try again on the next iteration of the</span> | |
6613 | <span class="comment">// application's main loop</span> | |
6614 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">yield</span><span class="special">();</span> | |
6615 | <span class="special">}</span> | |
6616 | <span class="keyword">return</span> <span class="identifier">error</span><span class="special">;</span> | |
6617 | <span class="special">}</span> | |
6618 | </pre> | |
6619 | <p> | |
6620 | </p> | |
6621 | <h6> | |
6622 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.h3"></a> | |
6623 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.filling_all_desired_data"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.filling_all_desired_data">Filling | |
6624 | All Desired Data</a> | |
6625 | </h6> | |
6626 | <p> | |
6627 | Given <code class="computeroutput"><span class="identifier">read_chunk</span><span class="special">()</span></code>, | |
6628 | we can straightforwardly iterate until we have all desired data: | |
6629 | </p> | |
6630 | <p> | |
6631 | </p> | |
6632 | <pre class="programlisting"><span class="comment">// keep reading until desired length, EOF or error</span> | |
6633 | <span class="comment">// may return both partial data and nonzero error</span> | |
6634 | <span class="keyword">int</span> <span class="identifier">read_desired</span><span class="special">(</span> <span class="identifier">NonblockingAPI</span> <span class="special">&</span> <span class="identifier">api</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&</span> <span class="identifier">data</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">desired</span><span class="special">)</span> <span class="special">{</span> | |
6635 | <span class="comment">// we're going to accumulate results into 'data'</span> | |
6636 | <span class="identifier">data</span><span class="special">.</span><span class="identifier">clear</span><span class="special">();</span> | |
6637 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">chunk</span><span class="special">;</span> | |
6638 | <span class="keyword">int</span> <span class="identifier">error</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> | |
6639 | <span class="keyword">while</span> <span class="special">(</span> <span class="identifier">data</span><span class="special">.</span><span class="identifier">length</span><span class="special">()</span> <span class="special"><</span> <span class="identifier">desired</span> <span class="special">&&</span> | |
6640 | <span class="special">(</span> <span class="identifier">error</span> <span class="special">=</span> <span class="identifier">read_chunk</span><span class="special">(</span> <span class="identifier">api</span><span class="special">,</span> <span class="identifier">chunk</span><span class="special">,</span> <span class="identifier">desired</span> <span class="special">-</span> <span class="identifier">data</span><span class="special">.</span><span class="identifier">length</span><span class="special">()</span> <span class="special">)</span> <span class="special">)</span> <span class="special">==</span> <span class="number">0</span><span class="special">)</span> <span class="special">{</span> | |
6641 | <span class="identifier">data</span><span class="special">.</span><span class="identifier">append</span><span class="special">(</span> <span class="identifier">chunk</span><span class="special">);</span> | |
6642 | <span class="special">}</span> | |
6643 | <span class="keyword">return</span> <span class="identifier">error</span><span class="special">;</span> | |
6644 | <span class="special">}</span> | |
6645 | </pre> | |
6646 | <p> | |
6647 | </p> | |
6648 | <p> | |
6649 | (Of <span class="emphasis"><em>course</em></span> there are more efficient ways to accumulate | |
6650 | string data. That's not the point of this example.) | |
6651 | </p> | |
6652 | <h6> | |
6653 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.h4"></a> | |
6654 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.wrapping_it_up"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.nonblocking.wrapping_it_up">Wrapping | |
6655 | it Up</a> | |
6656 | </h6> | |
6657 | <p> | |
6658 | Finally, we can define a relevant exception: | |
6659 | </p> | |
6660 | <p> | |
6661 | </p> | |
6662 | <pre class="programlisting"><span class="comment">// exception class augmented with both partially-read data and errorcode</span> | |
6663 | <span class="keyword">class</span> <span class="identifier">IncompleteRead</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span> <span class="special">{</span> | |
6664 | <span class="keyword">public</span><span class="special">:</span> | |
6665 | <span class="identifier">IncompleteRead</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">what</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">partial</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">:</span> | |
6666 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span><span class="special">(</span> <span class="identifier">what</span><span class="special">),</span> | |
6667 | <span class="identifier">partial_</span><span class="special">(</span> <span class="identifier">partial</span><span class="special">),</span> | |
6668 | <span class="identifier">ec_</span><span class="special">(</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">{</span> | |
6669 | <span class="special">}</span> | |
6670 | ||
6671 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">get_partial</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> | |
6672 | <span class="keyword">return</span> <span class="identifier">partial_</span><span class="special">;</span> | |
6673 | <span class="special">}</span> | |
6674 | ||
6675 | <span class="keyword">int</span> <span class="identifier">get_errorcode</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> | |
6676 | <span class="keyword">return</span> <span class="identifier">ec_</span><span class="special">;</span> | |
6677 | <span class="special">}</span> | |
6678 | ||
6679 | <span class="keyword">private</span><span class="special">:</span> | |
6680 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">partial_</span><span class="special">;</span> | |
6681 | <span class="keyword">int</span> <span class="identifier">ec_</span><span class="special">;</span> | |
6682 | <span class="special">};</span> | |
6683 | </pre> | |
6684 | <p> | |
6685 | </p> | |
6686 | <p> | |
6687 | and write a simple <code class="computeroutput"><span class="identifier">read</span><span class="special">()</span></code> function that either returns all desired | |
6688 | data or throws <code class="computeroutput"><span class="identifier">IncompleteRead</span></code>: | |
6689 | </p> | |
6690 | <p> | |
6691 | </p> | |
6692 | <pre class="programlisting"><span class="comment">// read all desired data or throw IncompleteRead</span> | |
6693 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">read</span><span class="special">(</span> <span class="identifier">NonblockingAPI</span> <span class="special">&</span> <span class="identifier">api</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">desired</span><span class="special">)</span> <span class="special">{</span> | |
6694 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">data</span><span class="special">;</span> | |
6695 | <span class="keyword">int</span> <span class="identifier">ec</span><span class="special">(</span> <span class="identifier">read_desired</span><span class="special">(</span> <span class="identifier">api</span><span class="special">,</span> <span class="identifier">data</span><span class="special">,</span> <span class="identifier">desired</span><span class="special">)</span> <span class="special">);</span> | |
6696 | ||
6697 | <span class="comment">// for present purposes, EOF isn't a failure</span> | |
6698 | <span class="keyword">if</span> <span class="special">(</span> <span class="number">0</span> <span class="special">==</span> <span class="identifier">ec</span> <span class="special">||</span> <span class="identifier">EOF</span> <span class="special">==</span> <span class="identifier">ec</span><span class="special">)</span> <span class="special">{</span> | |
6699 | <span class="keyword">return</span> <span class="identifier">data</span><span class="special">;</span> | |
6700 | <span class="special">}</span> | |
6701 | ||
6702 | <span class="comment">// oh oh, partial read</span> | |
6703 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostringstream</span> <span class="identifier">msg</span><span class="special">;</span> | |
6704 | <span class="identifier">msg</span> <span class="special"><<</span> <span class="string">"NonblockingAPI::read() error "</span> <span class="special"><<</span> <span class="identifier">ec</span> <span class="special"><<</span> <span class="string">" after "</span> | |
6705 | <span class="special"><<</span> <span class="identifier">data</span><span class="special">.</span><span class="identifier">length</span><span class="special">()</span> <span class="special"><<</span> <span class="string">" of "</span> <span class="special"><<</span> <span class="identifier">desired</span> <span class="special"><<</span> <span class="string">" characters"</span><span class="special">;</span> | |
6706 | <span class="keyword">throw</span> <span class="identifier">IncompleteRead</span><span class="special">(</span> <span class="identifier">msg</span><span class="special">.</span><span class="identifier">str</span><span class="special">(),</span> <span class="identifier">data</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">);</span> | |
6707 | <span class="special">}</span> | |
6708 | </pre> | |
6709 | <p> | |
6710 | </p> | |
6711 | <p> | |
6712 | Once we can transparently wait for the next main-loop iteration using | |
6713 | <a class="link" href="../../fiber_mgmt/this_fiber.html#this_fiber_yield"> <code class="computeroutput">this_fiber::yield()</code></a>, ordinary encapsulation Just Works. | |
6714 | </p> | |
6715 | <p> | |
6716 | The source code above is found in <a href="../../../../../examples/adapt_nonblocking.cpp" target="_top">adapt_nonblocking.cpp</a>. | |
6717 | </p> | |
6718 | </div> | |
6719 | <div class="section"> | |
6720 | <div class="titlepage"><div><div><h5 class="title"> | |
6721 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any"></a><a name="when_any"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any" title="when_any / when_all functionality">when_any | |
6722 | / when_all functionality</a> | |
6723 | </h5></div></div></div> | |
6724 | <div class="toc"><dl> | |
6725 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any">when_any</a></span></dt> | |
6726 | <dd><dl> | |
6727 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__simple_completion">when_any, | |
6728 | simple completion</a></span></dt> | |
6729 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__return_value">when_any, | |
6730 | return value</a></span></dt> | |
6731 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">when_any, | |
6732 | produce first outcome, whether result or exception</a></span></dt> | |
6733 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_success">when_any, | |
6734 | produce first success</a></span></dt> | |
6735 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__heterogeneous_types">when_any, | |
6736 | heterogeneous types</a></span></dt> | |
6737 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__a_dubious_alternative">when_any, | |
6738 | a dubious alternative</a></span></dt> | |
6739 | </dl></dd> | |
6740 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality">when_all | |
6741 | functionality</a></span></dt> | |
6742 | <dd><dl> | |
6743 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__simple_completion">when_all, | |
6744 | simple completion</a></span></dt> | |
6745 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__return_values">when_all, | |
6746 | return values</a></span></dt> | |
6747 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all_until_first_exception">when_all | |
6748 | until first exception</a></span></dt> | |
6749 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.wait_all__collecting_all_exceptions">wait_all, | |
6750 | collecting all exceptions</a></span></dt> | |
6751 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__heterogeneous_types">when_all, | |
6752 | heterogeneous types</a></span></dt> | |
6753 | </dl></dd> | |
6754 | </dl></div> | |
6755 | <h6> | |
6756 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.h0"></a> | |
6757 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.overview"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.overview">Overview</a> | |
6758 | </h6> | |
6759 | <p> | |
6760 | A bit of wisdom from the early days of computing still holds true today: | |
6761 | prefer to model program state using the instruction pointer rather than | |
6762 | with Boolean flags. In other words, if the program must <span class="quote">“<span class="quote">do something</span>”</span> | |
6763 | and then do something almost the same, but with minor changes... perhaps | |
6764 | parts of that something should be broken out as smaller separate functions, | |
6765 | rather than introducing flags to alter the internal behavior of a monolithic | |
6766 | function. | |
6767 | </p> | |
6768 | <p> | |
6769 | To that we would add: prefer to describe control flow using C++ native | |
6770 | constructs such as function calls, <code class="computeroutput"><span class="keyword">if</span></code>, | |
6771 | <code class="computeroutput"><span class="keyword">while</span></code>, <code class="computeroutput"><span class="keyword">for</span></code>, | |
6772 | <code class="computeroutput"><span class="keyword">do</span></code> et al. rather than as | |
6773 | chains of callbacks. | |
6774 | </p> | |
6775 | <p> | |
6776 | One of the great strengths of <span class="bold"><strong>Boost.Fiber</strong></span> | |
6777 | is the flexibility it confers on the coder to restructure an application | |
6778 | from chains of callbacks to straightforward C++ statement sequence, even | |
6779 | when code in that fiber is in fact interleaved with code running in other | |
6780 | fibers. | |
6781 | </p> | |
6782 | <p> | |
6783 | There has been much recent discussion about the benefits of when_any | |
6784 | and when_all functionality. When dealing with asynchronous and possibly | |
6785 | unreliable services, these are valuable idioms. But of course when_any | |
6786 | and when_all are closely tied to the use of chains of callbacks. | |
6787 | </p> | |
6788 | <p> | |
6789 | This section presents recipes for achieving the same ends, in the context | |
6790 | of a fiber that wants to <span class="quote">“<span class="quote">do something</span>”</span> when one or more | |
6791 | other independent activities have completed. Accordingly, these are | |
6792 | <code class="computeroutput"><span class="identifier">wait_something</span><span class="special">()</span></code> | |
6793 | functions rather than <code class="computeroutput"><span class="identifier">when_something</span><span class="special">()</span></code> functions. The expectation is that | |
6794 | the calling fiber asks to launch those independent activities, then waits | |
6795 | for them, then sequentially proceeds with whatever processing depends | |
6796 | on those results. | |
6797 | </p> | |
6798 | <p> | |
6799 | The function names shown (e.g. <a class="link" href="pooled_fixedsize.html#wait_first_simple"><code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code></a>) | |
6800 | are for illustrative purposes only, because all these functions have | |
6801 | been bundled into a single source file. Presumably, if (say) <a class="link" href="pooled_fixedsize.html#wait_first_success"><code class="computeroutput"><span class="identifier">wait_first_success</span><span class="special">()</span></code></a> | |
6802 | best suits your application needs, you could introduce that variant with | |
6803 | the name <code class="computeroutput"><span class="identifier">wait_any</span><span class="special">()</span></code>. | |
6804 | </p> | |
6805 | <div class="note"><table border="0" summary="Note"> | |
6806 | <tr> | |
6807 | <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> | |
6808 | <th align="left">Note</th> | |
6809 | </tr> | |
6810 | <tr><td align="left" valign="top"><p> | |
6811 | The functions presented in this section accept variadic argument lists | |
6812 | of task functions. Corresponding <code class="computeroutput"><span class="identifier">wait_something</span><span class="special">()</span></code> functions accepting a container of | |
6813 | task functions are left as an exercise for the interested reader. Those | |
6814 | should actually be simpler. Most of the complexity would arise from | |
6815 | overloading the same name for both purposes. | |
6816 | </p></td></tr> | |
6817 | </table></div> | |
6818 | <p> | |
6819 | All the source code for this section is found in <a href="../../../../../examples/wait_stuff.cpp" target="_top">wait_stuff.cpp</a>. | |
6820 | </p> | |
6821 | <h6> | |
6822 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.h1"></a> | |
6823 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.example_task_function"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.example_task_function">Example | |
6824 | Task Function</a> | |
6825 | </h6> | |
6826 | <p> | |
6827 | <a name="wait_sleeper"></a>We found it convenient to model an asynchronous | |
6828 | task using this function: | |
6829 | </p> | |
6830 | <p> | |
6831 | </p> | |
6832 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">></span> | |
6833 | <span class="identifier">T</span> <span class="identifier">sleeper_impl</span><span class="special">(</span> <span class="identifier">T</span> <span class="identifier">item</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">ms</span><span class="special">,</span> <span class="keyword">bool</span> <span class="identifier">thrw</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">)</span> <span class="special">{</span> | |
6834 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostringstream</span> <span class="identifier">descb</span><span class="special">,</span> <span class="identifier">funcb</span><span class="special">;</span> | |
6835 | <span class="identifier">descb</span> <span class="special"><<</span> <span class="identifier">item</span><span class="special">;</span> | |
6836 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">desc</span><span class="special">(</span> <span class="identifier">descb</span><span class="special">.</span><span class="identifier">str</span><span class="special">()</span> <span class="special">);</span> | |
6837 | <span class="identifier">funcb</span> <span class="special"><<</span> <span class="string">" sleeper("</span> <span class="special"><<</span> <span class="identifier">item</span> <span class="special"><<</span> <span class="string">")"</span><span class="special">;</span> | |
6838 | <span class="identifier">Verbose</span> <span class="identifier">v</span><span class="special">(</span> <span class="identifier">funcb</span><span class="special">.</span><span class="identifier">str</span><span class="special">()</span> <span class="special">);</span> | |
6839 | ||
6840 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">sleep_for</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">milliseconds</span><span class="special">(</span> <span class="identifier">ms</span><span class="special">)</span> <span class="special">);</span> | |
6841 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">thrw</span><span class="special">)</span> <span class="special">{</span> | |
6842 | <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span><span class="special">(</span> <span class="identifier">desc</span><span class="special">);</span> | |
6843 | <span class="special">}</span> | |
6844 | <span class="keyword">return</span> <span class="identifier">item</span><span class="special">;</span> | |
6845 | <span class="special">}</span> | |
6846 | </pre> | |
6847 | <p> | |
6848 | </p> | |
6849 | <p> | |
6850 | with type-specific <code class="computeroutput"><span class="identifier">sleeper</span><span class="special">()</span></code> <span class="quote">“<span class="quote">front ends</span>”</span> for <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>, <code class="computeroutput"><span class="keyword">double</span></code> | |
6851 | and <code class="computeroutput"><span class="keyword">int</span></code>. | |
6852 | </p> | |
6853 | <p> | |
6854 | <code class="computeroutput"><span class="identifier">Verbose</span></code> simply prints | |
6855 | a message to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span></code> on construction and destruction. | |
6856 | </p> | |
6857 | <p> | |
6858 | Basically: | |
6859 | </p> | |
6860 | <div class="orderedlist"><ol class="orderedlist" type="1"> | |
6861 | <li class="listitem"> | |
6862 | <code class="computeroutput"><span class="identifier">sleeper</span><span class="special">()</span></code> | |
6863 | prints a start message; | |
6864 | </li> | |
6865 | <li class="listitem"> | |
6866 | sleeps for the specified number of milliseconds; | |
6867 | </li> | |
6868 | <li class="listitem"> | |
6869 | if <code class="computeroutput"><span class="identifier">thrw</span></code> is passed | |
6870 | as <code class="computeroutput"><span class="keyword">true</span></code>, throws a string | |
6871 | description of the passed <code class="computeroutput"><span class="identifier">item</span></code>; | |
6872 | </li> | |
6873 | <li class="listitem"> | |
6874 | else returns the passed <code class="computeroutput"><span class="identifier">item</span></code>. | |
6875 | </li> | |
6876 | <li class="listitem"> | |
6877 | On the way out, <code class="computeroutput"><span class="identifier">sleeper</span><span class="special">()</span></code> produces a stop message. | |
6878 | </li> | |
6879 | </ol></div> | |
6880 | <p> | |
6881 | This function will feature in the example calls to the various functions | |
6882 | presented below. | |
6883 | </p> | |
6884 | <div class="section"> | |
6885 | <div class="titlepage"><div><div><h6 class="title"> | |
6886 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any" title="when_any">when_any</a> | |
6887 | </h6></div></div></div> | |
6888 | <div class="toc"><dl> | |
6889 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__simple_completion">when_any, | |
6890 | simple completion</a></span></dt> | |
6891 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__return_value">when_any, | |
6892 | return value</a></span></dt> | |
6893 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception">when_any, | |
6894 | produce first outcome, whether result or exception</a></span></dt> | |
6895 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_success">when_any, | |
6896 | produce first success</a></span></dt> | |
6897 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__heterogeneous_types">when_any, | |
6898 | heterogeneous types</a></span></dt> | |
6899 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__a_dubious_alternative">when_any, | |
6900 | a dubious alternative</a></span></dt> | |
6901 | </dl></div> | |
6902 | <div class="section"> | |
6903 | <div class="titlepage"><div><div><h6 class="title"> | |
6904 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__simple_completion"></a><a name="wait_first_simple_section"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__simple_completion" title="when_any, simple completion">when_any, | |
6905 | simple completion</a> | |
6906 | </h6></div></div></div> | |
6907 | <p> | |
6908 | The simplest case is when you only need to know that the first of | |
6909 | a set of asynchronous tasks has completed — but you don't need to obtain | |
6910 | a return value, and you're confident that they will not throw exceptions. | |
6911 | </p> | |
6912 | <p> | |
6913 | <a name="wait_done"></a>For this we introduce a <code class="computeroutput"><span class="identifier">Done</span></code> | |
6914 | class to wrap a <code class="computeroutput"><span class="keyword">bool</span></code> | |
6915 | variable with a <a class="link" href="pooled_fixedsize.html#class_condition_variable"> <code class="computeroutput">condition_variable</code></a> and a <a class="link" href="pooled_fixedsize.html#class_mutex"> <code class="computeroutput">mutex</code></a>: | |
6916 | </p> | |
6917 | <p> | |
6918 | </p> | |
6919 | <pre class="programlisting"><span class="comment">// Wrap canonical pattern for condition_variable + bool flag</span> | |
6920 | <span class="keyword">struct</span> <span class="identifier">Done</span> <span class="special">{</span> | |
6921 | <span class="keyword">private</span><span class="special">:</span> | |
6922 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">condition_variable</span> <span class="identifier">cond</span><span class="special">;</span> | |
6923 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span> <span class="identifier">mutex</span><span class="special">;</span> | |
6924 | <span class="keyword">bool</span> <span class="identifier">ready</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span> | |
6925 | ||
6926 | <span class="keyword">public</span><span class="special">:</span> | |
6927 | <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">Done</span> <span class="special">></span> <span class="identifier">ptr</span><span class="special">;</span> | |
6928 | ||
6929 | <span class="keyword">void</span> <span class="identifier">wait</span><span class="special">()</span> <span class="special">{</span> | |
6930 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">></span> <span class="identifier">lock</span><span class="special">(</span> <span class="identifier">mutex</span><span class="special">);</span> | |
6931 | <span class="identifier">cond</span><span class="special">.</span><span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lock</span><span class="special">,</span> <span class="special">[</span><span class="keyword">this</span><span class="special">](){</span> <span class="keyword">return</span> <span class="identifier">ready</span><span class="special">;</span> <span class="special">});</span> | |
6932 | <span class="special">}</span> | |
6933 | ||
6934 | <span class="keyword">void</span> <span class="identifier">notify</span><span class="special">()</span> <span class="special">{</span> | |
6935 | <span class="special">{</span> | |
6936 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">></span> <span class="identifier">lock</span><span class="special">(</span> <span class="identifier">mutex</span><span class="special">);</span> | |
6937 | <span class="identifier">ready</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span> | |
6938 | <span class="special">}</span> <span class="comment">// release mutex</span> | |
6939 | <span class="identifier">cond</span><span class="special">.</span><span class="identifier">notify_one</span><span class="special">();</span> | |
6940 | <span class="special">}</span> | |
6941 | <span class="special">};</span> | |
6942 | </pre> | |
6943 | <p> | |
6944 | </p> | |
6945 | <p> | |
6946 | The pattern we follow throughout this section is to pass a <a href="http://www.cplusplus.com/reference/memory/shared_ptr/" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><></span></code></a> | |
6947 | to the relevant synchronization object to the various tasks' fiber | |
6948 | functions. This eliminates nagging questions about the lifespan of | |
6949 | the synchronization object relative to the last of the fibers. | |
6950 | </p> | |
6951 | <p> | |
6952 | <a name="wait_first_simple"></a><code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code> uses that tactic for <a class="link" href="pooled_fixedsize.html#wait_done"><code class="computeroutput"><span class="identifier">Done</span></code></a>: | |
6953 | </p> | |
6954 | <p> | |
6955 | </p> | |
6956 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
6957 | <span class="keyword">void</span> <span class="identifier">wait_first_simple</span><span class="special">(</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
6958 | <span class="comment">// Use shared_ptr because each function's fiber will bind it separately,</span> | |
6959 | <span class="comment">// and we're going to return before the last of them completes.</span> | |
6960 | <span class="keyword">auto</span> <span class="identifier">done</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">Done</span> <span class="special">>()</span> <span class="special">);</span> | |
6961 | <span class="identifier">wait_first_simple_impl</span><span class="special">(</span> <span class="identifier">done</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
6962 | <span class="identifier">done</span><span class="special">-></span><span class="identifier">wait</span><span class="special">();</span> | |
6963 | <span class="special">}</span> | |
6964 | </pre> | |
6965 | <p> | |
6966 | </p> | |
6967 | <p> | |
6968 | <a name="wait_first_simple_impl"></a><code class="computeroutput"><span class="identifier">wait_first_simple_impl</span><span class="special">()</span></code> is an ordinary recursion over the | |
6969 | argument pack, capturing <code class="computeroutput"><span class="identifier">Done</span><span class="special">::</span><span class="identifier">ptr</span></code> | |
6970 | for each new fiber: | |
6971 | </p> | |
6972 | <p> | |
6973 | </p> | |
6974 | <pre class="programlisting"><span class="comment">// Degenerate case: when there are no functions to wait for, return</span> | |
6975 | <span class="comment">// immediately.</span> | |
6976 | <span class="keyword">void</span> <span class="identifier">wait_first_simple_impl</span><span class="special">(</span> <span class="identifier">Done</span><span class="special">::</span><span class="identifier">ptr</span><span class="special">)</span> <span class="special">{</span> | |
6977 | <span class="special">}</span> | |
6978 | ||
6979 | <span class="comment">// When there's at least one function to wait for, launch it and recur to</span> | |
6980 | <span class="comment">// process the rest.</span> | |
6981 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
6982 | <span class="keyword">void</span> <span class="identifier">wait_first_simple_impl</span><span class="special">(</span> <span class="identifier">Done</span><span class="special">::</span><span class="identifier">ptr</span> <span class="identifier">done</span><span class="special">,</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
6983 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span><span class="special">(</span> <span class="special">[</span><span class="identifier">done</span><span class="special">,</span> <span class="identifier">function</span><span class="special">](){</span> | |
6984 | <span class="identifier">function</span><span class="special">();</span> | |
6985 | <span class="identifier">done</span><span class="special">-></span><span class="identifier">notify</span><span class="special">();</span> | |
6986 | <span class="special">}).</span><span class="identifier">detach</span><span class="special">();</span> | |
6987 | <span class="identifier">wait_first_simple_impl</span><span class="special">(</span> <span class="identifier">done</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
6988 | <span class="special">}</span> | |
6989 | </pre> | |
6990 | <p> | |
6991 | </p> | |
6992 | <p> | |
6993 | The body of the fiber's lambda is extremely simple, as promised: | |
6994 | call the function, notify <a class="link" href="pooled_fixedsize.html#wait_done"><code class="computeroutput"><span class="identifier">Done</span></code></a> when it returns. The | |
6995 | first fiber to do so allows <code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code> to return — which is why it's useful | |
6996 | to have <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span><span class="identifier">Done</span><span class="special">></span></code> | |
6997 | manage the lifespan of our <code class="computeroutput"><span class="identifier">Done</span></code> | |
6998 | object rather than declaring it as a stack variable in <code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code>. | |
6999 | </p> | |
7000 | <p> | |
7001 | This is how you might call it: | |
7002 | </p> | |
7003 | <p> | |
7004 | </p> | |
7005 | <pre class="programlisting"><span class="identifier">wait_first_simple</span><span class="special">(</span> | |
7006 | <span class="special">[](){</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfs_long"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
7007 | <span class="special">[](){</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfs_medium"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7008 | <span class="special">[](){</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfs_short"</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
7009 | </pre> | |
7010 | <p> | |
7011 | </p> | |
7012 | <p> | |
7013 | In this example, control resumes after <code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code> when <a class="link" href="pooled_fixedsize.html#wait_sleeper"><code class="computeroutput"><span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfs_short"</span><span class="special">,</span> | |
7014 | <span class="number">50</span><span class="special">)</span></code></a> | |
7015 | completes — even though the other two <code class="computeroutput"><span class="identifier">sleeper</span><span class="special">()</span></code> fibers are still running. | |
7016 | </p> | |
7017 | </div> | |
7018 | <div class="section"> | |
7019 | <div class="titlepage"><div><div><h6 class="title"> | |
7020 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__return_value"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__return_value" title="when_any, return value">when_any, | |
7021 | return value</a> | |
7022 | </h6></div></div></div> | |
7023 | <p> | |
7024 | It seems more useful to add the ability to capture the return value | |
7025 | from the first of the task functions to complete. Again, we assume | |
7026 | that none will throw an exception. | |
7027 | </p> | |
7028 | <p> | |
7029 | One tactic would be to adapt our <a class="link" href="pooled_fixedsize.html#wait_done"><code class="computeroutput"><span class="identifier">Done</span></code></a> class to store the | |
7030 | first of the return values, rather than a simple <code class="computeroutput"><span class="keyword">bool</span></code>. | |
7031 | However, we choose instead to use a <a class="link" href="pooled_fixedsize.html#class_unbounded_channel"> <code class="computeroutput">unbounded_channel<></code></a>. | |
7032 | We'll only need to enqueue the first value, so we'll <a class="link" href="pooled_fixedsize.html#unbounded_channel_close"> <code class="computeroutput">unbounded_channel::close()</code></a> it | |
7033 | once we've retrieved that value. Subsequent <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code> calls will return <code class="computeroutput"><span class="identifier">closed</span></code>. | |
7034 | </p> | |
7035 | <p> | |
7036 | <a name="wait_first_value"></a> | |
7037 | </p> | |
7038 | <pre class="programlisting"><span class="comment">// Assume that all passed functions have the same return type. The return type</span> | |
7039 | <span class="comment">// of wait_first_value() is the return type of the first passed function. It is</span> | |
7040 | <span class="comment">// simply invalid to pass NO functions.</span> | |
7041 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7042 | <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> | |
7043 | <span class="identifier">wait_first_value</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7044 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">return_t</span><span class="special">;</span> | |
7045 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">channel_t</span><span class="special">;</span> | |
7046 | <span class="keyword">auto</span> <span class="identifier">channelp</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">channel_t</span> <span class="special">>()</span> <span class="special">);</span> | |
7047 | <span class="comment">// launch all the relevant fibers</span> | |
7048 | <span class="identifier">wait_first_value_impl</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">>(</span> <span class="identifier">channelp</span><span class="special">,</span> | |
7049 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">),</span> | |
7050 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
7051 | <span class="comment">// retrieve the first value</span> | |
7052 | <span class="identifier">return_t</span> <span class="identifier">value</span><span class="special">(</span> <span class="identifier">channelp</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span> <span class="special">);</span> | |
7053 | <span class="comment">// close the channel: no subsequent push() has to succeed</span> | |
7054 | <span class="identifier">channelp</span><span class="special">-></span><span class="identifier">close</span><span class="special">();</span> | |
7055 | <span class="keyword">return</span> <span class="identifier">value</span><span class="special">;</span> | |
7056 | <span class="special">}</span> | |
7057 | </pre> | |
7058 | <p> | |
7059 | </p> | |
7060 | <p> | |
7061 | <a name="wait_first_value_impl"></a>The meat of the <code class="computeroutput"><span class="identifier">wait_first_value_impl</span><span class="special">()</span></code> | |
7062 | function is as you might expect: | |
7063 | </p> | |
7064 | <p> | |
7065 | </p> | |
7066 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Fn</span> <span class="special">></span> | |
7067 | <span class="keyword">void</span> <span class="identifier">wait_first_value_impl</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">T</span> <span class="special">></span> <span class="special">></span> <span class="identifier">channel</span><span class="special">,</span> | |
7068 | <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">)</span> <span class="special">{</span> | |
7069 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span><span class="special">(</span> <span class="special">[</span><span class="identifier">channel</span><span class="special">,</span> <span class="identifier">function</span><span class="special">](){</span> | |
7070 | <span class="comment">// Ignore channel_op_status returned by push():</span> | |
7071 | <span class="comment">// might be closed; we simply don't care.</span> | |
7072 | <span class="identifier">channel</span><span class="special">-></span><span class="identifier">push</span><span class="special">(</span> <span class="identifier">function</span><span class="special">()</span> <span class="special">);</span> | |
7073 | <span class="special">}).</span><span class="identifier">detach</span><span class="special">();</span> | |
7074 | <span class="special">}</span> | |
7075 | </pre> | |
7076 | <p> | |
7077 | </p> | |
7078 | <p> | |
7079 | It calls the passed function, pushes its return value and ignores | |
7080 | the <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code> | |
7081 | result. You might call it like this: | |
7082 | </p> | |
7083 | <p> | |
7084 | </p> | |
7085 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">wait_first_value</span><span class="special">(</span> | |
7086 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfv_third"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
7087 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfv_second"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7088 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfv_first"</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
7089 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_first_value() => "</span> <span class="special"><<</span> <span class="identifier">result</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
7090 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">result</span> <span class="special">==</span> <span class="string">"wfv_first"</span><span class="special">);</span> | |
7091 | </pre> | |
7092 | <p> | |
7093 | </p> | |
7094 | </div> | |
7095 | <div class="section"> | |
7096 | <div class="titlepage"><div><div><h6 class="title"> | |
7097 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_outcome__whether_result_or_exception" title="when_any, produce first outcome, whether result or exception">when_any, | |
7098 | produce first outcome, whether result or exception</a> | |
7099 | </h6></div></div></div> | |
7100 | <p> | |
7101 | We may not be running in an environment in which we can guarantee | |
7102 | no exception will be thrown by any of our task functions. In that | |
7103 | case, the above implementations of <code class="computeroutput"><span class="identifier">wait_first_something</span><span class="special">()</span></code> would be naïve: as mentioned in | |
7104 | <a class="link" href="../../fiber_mgmt.html#exceptions">the section on Fiber Management</a>, | |
7105 | an uncaught exception in one of our task fibers would cause <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span><span class="special">()</span></code> | |
7106 | to be called. | |
7107 | </p> | |
7108 | <p> | |
7109 | Let's at least ensure that such an exception would propagate to the | |
7110 | fiber awaiting the first result. We can use <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a> to | |
7111 | transport either a return value or an exception. Therefore, we will | |
7112 | change <a class="link" href="pooled_fixedsize.html#wait_first_value"><code class="computeroutput"><span class="identifier">wait_first_value</span><span class="special">()</span></code></a>'s <a class="link" href="pooled_fixedsize.html#class_unbounded_channel"> <code class="computeroutput">unbounded_channel<></code></a> to | |
7113 | hold <code class="computeroutput"><span class="identifier">future</span><span class="special"><</span> | |
7114 | <span class="identifier">T</span> <span class="special">></span></code> | |
7115 | items instead of simply <code class="computeroutput"><span class="identifier">T</span></code>. | |
7116 | </p> | |
7117 | <p> | |
7118 | Once we have a <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> in hand, all we need do is | |
7119 | call <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a>, which will either return the value | |
7120 | or rethrow the exception. | |
7121 | </p> | |
7122 | <p> | |
7123 | <a name="wait_first_outcome"></a> | |
7124 | </p> | |
7125 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7126 | <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> | |
7127 | <span class="identifier">wait_first_outcome</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7128 | <span class="comment">// In this case, the value we pass through the channel is actually a</span> | |
7129 | <span class="comment">// future -- which is already ready. future can carry either a value or an</span> | |
7130 | <span class="comment">// exception.</span> | |
7131 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">return_t</span><span class="special">;</span> | |
7132 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">future_t</span><span class="special">;</span> | |
7133 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">future_t</span> <span class="special">></span> <span class="identifier">channel_t</span><span class="special">;</span> | |
7134 | <span class="keyword">auto</span> <span class="identifier">channelp</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">channel_t</span> <span class="special">>()</span> <span class="special">);</span> | |
7135 | <span class="comment">// launch all the relevant fibers</span> | |
7136 | <span class="identifier">wait_first_outcome_impl</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">>(</span> <span class="identifier">channelp</span><span class="special">,</span> | |
7137 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">),</span> | |
7138 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
7139 | <span class="comment">// retrieve the first future</span> | |
7140 | <span class="identifier">future_t</span> <span class="identifier">future</span><span class="special">(</span> <span class="identifier">channelp</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span> <span class="special">);</span> | |
7141 | <span class="comment">// close the channel: no subsequent push() has to succeed</span> | |
7142 | <span class="identifier">channelp</span><span class="special">-></span><span class="identifier">close</span><span class="special">();</span> | |
7143 | <span class="comment">// either return value or throw exception</span> | |
7144 | <span class="keyword">return</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span> | |
7145 | <span class="special">}</span> | |
7146 | </pre> | |
7147 | <p> | |
7148 | </p> | |
7149 | <p> | |
7150 | So far so good — but there's a timing issue. How should we obtain the | |
7151 | <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> | |
7152 | to <a class="link" href="pooled_fixedsize.html#unbounded_channel_push"> <code class="computeroutput">unbounded_channel::push()</code></a> on the channel? | |
7153 | </p> | |
7154 | <p> | |
7155 | We could call <a class="link" href="pooled_fixedsize.html#fibers_async"> <code class="computeroutput">fibers::async()</code></a>. That would certainly produce | |
7156 | a <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> | |
7157 | for the task function. The trouble is that it would return too quickly! | |
7158 | We only want <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> items for <span class="emphasis"><em>completed</em></span> | |
7159 | tasks on our <code class="computeroutput"><span class="identifier">unbounded_channel</span><span class="special"><></span></code>. In fact, we only want the | |
7160 | <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> | |
7161 | for the one that completes first. If each fiber launched by <code class="computeroutput"><span class="identifier">wait_first_outcome</span><span class="special">()</span></code> | |
7162 | were to <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code> | |
7163 | the result of calling <code class="computeroutput"><span class="identifier">async</span><span class="special">()</span></code>, the channel would only ever report | |
7164 | the result of the leftmost task item — <span class="emphasis"><em>not</em></span> the | |
7165 | one that completes most quickly. | |
7166 | </p> | |
7167 | <p> | |
7168 | Calling <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a> on the future returned by <code class="computeroutput"><span class="identifier">async</span><span class="special">()</span></code> | |
7169 | wouldn't be right. You can only call <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code> once per <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> instance! And if there were | |
7170 | an exception, it would be rethrown inside the helper fiber at the | |
7171 | producer end of the channel, rather than propagated to the consumer | |
7172 | end. | |
7173 | </p> | |
7174 | <p> | |
7175 | We could call <a class="link" href="pooled_fixedsize.html#future_wait"> <code class="computeroutput">future::wait()</code></a>. That would block the helper | |
7176 | fiber until the <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> became ready, at which point | |
7177 | we could <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code> | |
7178 | it to be retrieved by <code class="computeroutput"><span class="identifier">wait_first_outcome</span><span class="special">()</span></code>. | |
7179 | </p> | |
7180 | <p> | |
7181 | That would work — but there's a simpler tactic that avoids creating | |
7182 | an extra fiber. We can wrap the task function in a <a class="link" href="pooled_fixedsize.html#class_packaged_task"> <code class="computeroutput">packaged_task<></code></a>. | |
7183 | While one naturally thinks of passing a <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code> to a new fiber — that is, in | |
7184 | fact, what <code class="computeroutput"><span class="identifier">async</span><span class="special">()</span></code> does — in this case, we're already | |
7185 | running in the helper fiber at the producer end of the channel! We | |
7186 | can simply <span class="emphasis"><em>call</em></span> the <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code>. On return from that call, | |
7187 | the task function has completed, meaning that the <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> obtained from the <code class="computeroutput"><span class="identifier">packaged_task</span><span class="special"><></span></code> | |
7188 | is certain to be ready. At that point we can simply <code class="computeroutput"><span class="identifier">push</span><span class="special">()</span></code> | |
7189 | it to the channel. | |
7190 | </p> | |
7191 | <p> | |
7192 | <a name="wait_first_outcome_impl"></a> | |
7193 | </p> | |
7194 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">CHANNELP</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Fn</span> <span class="special">></span> | |
7195 | <span class="keyword">void</span> <span class="identifier">wait_first_outcome_impl</span><span class="special">(</span> <span class="identifier">CHANNELP</span> <span class="identifier">channel</span><span class="special">,</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">)</span> <span class="special">{</span> | |
7196 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span><span class="special">(</span> | |
7197 | <span class="comment">// Use std::bind() here for C++11 compatibility. C++11 lambda capture</span> | |
7198 | <span class="comment">// can't move a move-only Fn type, but bind() can. Let bind() move the</span> | |
7199 | <span class="comment">// channel pointer and the function into the bound object, passing</span> | |
7200 | <span class="comment">// references into the lambda.</span> | |
7201 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span> | |
7202 | <span class="special">[](</span> <span class="identifier">CHANNELP</span> <span class="special">&</span> <span class="identifier">channel</span><span class="special">,</span> | |
7203 | <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>::</span><span class="identifier">type</span> <span class="special">&</span> <span class="identifier">function</span><span class="special">)</span> <span class="special">{</span> | |
7204 | <span class="comment">// Instantiate a packaged_task to capture any exception thrown by</span> | |
7205 | <span class="comment">// function.</span> | |
7206 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">packaged_task</span><span class="special"><</span> <span class="identifier">T</span><span class="special">()</span> <span class="special">></span> <span class="identifier">task</span><span class="special">(</span> <span class="identifier">function</span><span class="special">);</span> | |
7207 | <span class="comment">// Immediately run this packaged_task on same fiber. We want</span> | |
7208 | <span class="comment">// function() to have completed BEFORE we push the future.</span> | |
7209 | <span class="identifier">task</span><span class="special">();</span> | |
7210 | <span class="comment">// Pass the corresponding future to consumer. Ignore</span> | |
7211 | <span class="comment">// channel_op_status returned by push(): might be closed; we</span> | |
7212 | <span class="comment">// simply don't care.</span> | |
7213 | <span class="identifier">channel</span><span class="special">-></span><span class="identifier">push</span><span class="special">(</span> <span class="identifier">task</span><span class="special">.</span><span class="identifier">get_future</span><span class="special">()</span> <span class="special">);</span> | |
7214 | <span class="special">},</span> | |
7215 | <span class="identifier">channel</span><span class="special">,</span> | |
7216 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">)</span> | |
7217 | <span class="special">)).</span><span class="identifier">detach</span><span class="special">();</span> | |
7218 | <span class="special">}</span> | |
7219 | </pre> | |
7220 | <p> | |
7221 | </p> | |
7222 | <p> | |
7223 | Calling it might look like this: | |
7224 | </p> | |
7225 | <p> | |
7226 | </p> | |
7227 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">wait_first_outcome</span><span class="special">(</span> | |
7228 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfos_first"</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">},</span> | |
7229 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfos_second"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7230 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfos_third"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">});</span> | |
7231 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_first_outcome(success) => "</span> <span class="special"><<</span> <span class="identifier">result</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
7232 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">result</span> <span class="special">==</span> <span class="string">"wfos_first"</span><span class="special">);</span> | |
7233 | ||
7234 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">thrown</span><span class="special">;</span> | |
7235 | <span class="keyword">try</span> <span class="special">{</span> | |
7236 | <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">wait_first_outcome</span><span class="special">(</span> | |
7237 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfof_first"</span><span class="special">,</span> <span class="number">50</span><span class="special">,</span> <span class="keyword">true</span><span class="special">);</span> <span class="special">},</span> | |
7238 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfof_second"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7239 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfof_third"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">});</span> | |
7240 | <span class="special">}</span> <span class="keyword">catch</span> <span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">e</span><span class="special">)</span> <span class="special">{</span> | |
7241 | <span class="identifier">thrown</span> <span class="special">=</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">();</span> | |
7242 | <span class="special">}</span> | |
7243 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_first_outcome(fail) threw '"</span> <span class="special"><<</span> <span class="identifier">thrown</span> | |
7244 | <span class="special"><<</span> <span class="string">"'"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
7245 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">thrown</span> <span class="special">==</span> <span class="string">"wfof_first"</span><span class="special">);</span> | |
7246 | </pre> | |
7247 | <p> | |
7248 | </p> | |
7249 | </div> | |
7250 | <div class="section"> | |
7251 | <div class="titlepage"><div><div><h6 class="title"> | |
7252 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_success"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__produce_first_success" title="when_any, produce first success">when_any, | |
7253 | produce first success</a> | |
7254 | </h6></div></div></div> | |
7255 | <p> | |
7256 | One scenario for <span class="quote">“<span class="quote">when_any</span>”</span> functionality is when we're | |
7257 | redundantly contacting some number of possibly-unreliable web services. | |
7258 | Not only might they be slow — any one of them might produce a failure | |
7259 | rather than the desired result. | |
7260 | </p> | |
7261 | <p> | |
7262 | In such a case, <a class="link" href="pooled_fixedsize.html#wait_first_outcome"><code class="computeroutput"><span class="identifier">wait_first_outcome</span><span class="special">()</span></code></a> | |
7263 | isn't the right approach. If one of the services produces an error | |
7264 | quickly, while another follows up with a real answer, we don't want | |
7265 | to prefer the error just because it arrived first! | |
7266 | </p> | |
7267 | <p> | |
7268 | Given the <code class="computeroutput"><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">future</span><span class="special"><</span> <span class="identifier">T</span> | |
7269 | <span class="special">></span> <span class="special">></span></code> | |
7270 | we already constructed for <code class="computeroutput"><span class="identifier">wait_first_outcome</span><span class="special">()</span></code>, though, we can readily recast | |
7271 | the interface function to deliver the first <span class="emphasis"><em>successful</em></span> | |
7272 | result. | |
7273 | </p> | |
7274 | <p> | |
7275 | That does beg the question: what if <span class="emphasis"><em>all</em></span> the | |
7276 | task functions throw an exception? In that case we'd probably better | |
7277 | know about it. | |
7278 | </p> | |
7279 | <p> | |
7280 | <a name="exception_list"></a>The <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4407.html#parallel.exceptions.synopsis" target="_top">C++ | |
7281 | Parallelism Draft Technical Specification</a> proposes a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_list</span></code> exception capable | |
7282 | of delivering a collection of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>s. | |
7283 | Until that becomes universally available, let's fake up an <code class="computeroutput"><span class="identifier">exception_list</span></code> of our own: | |
7284 | </p> | |
7285 | <p> | |
7286 | </p> | |
7287 | <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">exception_list</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span> <span class="special">{</span> | |
7288 | <span class="keyword">public</span><span class="special">:</span> | |
7289 | <span class="identifier">exception_list</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">what</span><span class="special">)</span> <span class="special">:</span> | |
7290 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span><span class="special">(</span> <span class="identifier">what</span><span class="special">)</span> <span class="special">{</span> | |
7291 | <span class="special">}</span> | |
7292 | ||
7293 | <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="special">></span> <span class="identifier">bundle_t</span><span class="special">;</span> | |
7294 | ||
7295 | <span class="comment">// N4407 proposed std::exception_list API</span> | |
7296 | <span class="keyword">typedef</span> <span class="identifier">bundle_t</span><span class="special">::</span><span class="identifier">const_iterator</span> <span class="identifier">iterator</span><span class="special">;</span> | |
7297 | ||
7298 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">size</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
7299 | <span class="keyword">return</span> <span class="identifier">bundle_</span><span class="special">.</span><span class="identifier">size</span><span class="special">();</span> | |
7300 | <span class="special">}</span> | |
7301 | ||
7302 | <span class="identifier">iterator</span> <span class="identifier">begin</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
7303 | <span class="keyword">return</span> <span class="identifier">bundle_</span><span class="special">.</span><span class="identifier">begin</span><span class="special">();</span> | |
7304 | <span class="special">}</span> | |
7305 | ||
7306 | <span class="identifier">iterator</span> <span class="identifier">end</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
7307 | <span class="keyword">return</span> <span class="identifier">bundle_</span><span class="special">.</span><span class="identifier">end</span><span class="special">();</span> | |
7308 | <span class="special">}</span> | |
7309 | ||
7310 | <span class="comment">// extension to populate</span> | |
7311 | <span class="keyword">void</span> <span class="identifier">add</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">ep</span><span class="special">)</span> <span class="special">{</span> | |
7312 | <span class="identifier">bundle_</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span> <span class="identifier">ep</span><span class="special">);</span> | |
7313 | <span class="special">}</span> | |
7314 | ||
7315 | <span class="keyword">private</span><span class="special">:</span> | |
7316 | <span class="identifier">bundle_t</span> <span class="identifier">bundle_</span><span class="special">;</span> | |
7317 | <span class="special">};</span> | |
7318 | </pre> | |
7319 | <p> | |
7320 | </p> | |
7321 | <p> | |
7322 | Now we can build <code class="computeroutput"><span class="identifier">wait_first_success</span><span class="special">()</span></code>, using <a class="link" href="pooled_fixedsize.html#wait_first_outcome_impl"><code class="computeroutput"><span class="identifier">wait_first_outcome_impl</span><span class="special">()</span></code></a>. | |
7323 | </p> | |
7324 | <p> | |
7325 | Instead of retrieving only the first <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> from the channel, we must | |
7326 | now loop over <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> items. Of course we must | |
7327 | limit that iteration! If we launch only <code class="computeroutput"><span class="identifier">count</span></code> | |
7328 | producer fibers, the <code class="computeroutput"><span class="special">(</span><span class="identifier">count</span><span class="special">+</span><span class="number">1</span><span class="special">)</span></code> | |
7329 | <sup>st</sup> | |
7330 | <a class="link" href="pooled_fixedsize.html#unbounded_channel_pop"> <code class="computeroutput">unbounded_channel::pop()</code></a> call would block forever. | |
7331 | </p> | |
7332 | <p> | |
7333 | Given a ready <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code>, we can distinguish failure | |
7334 | by calling <a class="link" href="pooled_fixedsize.html#future_get_exception_ptr"> <code class="computeroutput">future::get_exception_ptr()</code></a>. If | |
7335 | the <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> | |
7336 | in fact contains a result rather than an exception, <code class="computeroutput"><span class="identifier">get_exception_ptr</span><span class="special">()</span></code> | |
7337 | returns <code class="computeroutput"><span class="keyword">nullptr</span></code>. In | |
7338 | that case, we can confidently call <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a> to return | |
7339 | that result to our caller. | |
7340 | </p> | |
7341 | <p> | |
7342 | If the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code> is <span class="emphasis"><em>not</em></span> | |
7343 | <code class="computeroutput"><span class="keyword">nullptr</span></code>, though, we | |
7344 | collect it into our pending <code class="computeroutput"><span class="identifier">exception_list</span></code> | |
7345 | and loop back for the next <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code> from the channel. | |
7346 | </p> | |
7347 | <p> | |
7348 | If we fall out of the loop — if every single task fiber threw an exception | |
7349 | — we throw the <code class="computeroutput"><span class="identifier">exception_list</span></code> | |
7350 | exception into which we've been collecting those <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>s. | |
7351 | </p> | |
7352 | <p> | |
7353 | <a name="wait_first_success"></a> | |
7354 | </p> | |
7355 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7356 | <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> | |
7357 | <span class="identifier">wait_first_success</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7358 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">count</span><span class="special">(</span> <span class="number">1</span> <span class="special">+</span> <span class="keyword">sizeof</span> <span class="special">...</span> <span class="special">(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">);</span> | |
7359 | <span class="comment">// In this case, the value we pass through the channel is actually a</span> | |
7360 | <span class="comment">// future -- which is already ready. future can carry either a value or an</span> | |
7361 | <span class="comment">// exception.</span> | |
7362 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>::</span><span class="identifier">type</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">return_t</span><span class="special">;</span> | |
7363 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">future_t</span><span class="special">;</span> | |
7364 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">future_t</span> <span class="special">></span> <span class="identifier">channel_t</span><span class="special">;</span> | |
7365 | <span class="keyword">auto</span> <span class="identifier">channelp</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">channel_t</span> <span class="special">>()</span> <span class="special">);</span> | |
7366 | <span class="comment">// launch all the relevant fibers</span> | |
7367 | <span class="identifier">wait_first_outcome_impl</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">>(</span> <span class="identifier">channelp</span><span class="special">,</span> | |
7368 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">),</span> | |
7369 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
7370 | <span class="comment">// instantiate exception_list, just in case</span> | |
7371 | <span class="identifier">exception_list</span> <span class="identifier">exceptions</span><span class="special">(</span><span class="string">"wait_first_success() produced only errors"</span><span class="special">);</span> | |
7372 | <span class="comment">// retrieve up to 'count' results -- but stop there!</span> | |
7373 | <span class="keyword">for</span> <span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="identifier">count</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{</span> | |
7374 | <span class="comment">// retrieve the next future</span> | |
7375 | <span class="identifier">future_t</span> <span class="identifier">future</span><span class="special">(</span> <span class="identifier">channelp</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span> <span class="special">);</span> | |
7376 | <span class="comment">// retrieve exception_ptr if any</span> | |
7377 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">error</span><span class="special">(</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get_exception_ptr</span><span class="special">()</span> <span class="special">);</span> | |
7378 | <span class="comment">// if no error, then yay, return value</span> | |
7379 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">error</span><span class="special">)</span> <span class="special">{</span> | |
7380 | <span class="comment">// close the channel: no subsequent push() has to succeed</span> | |
7381 | <span class="identifier">channelp</span><span class="special">-></span><span class="identifier">close</span><span class="special">();</span> | |
7382 | <span class="comment">// show caller the value we got</span> | |
7383 | <span class="keyword">return</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span> | |
7384 | <span class="special">}</span> | |
7385 | ||
7386 | <span class="comment">// error is non-null: collect</span> | |
7387 | <span class="identifier">exceptions</span><span class="special">.</span><span class="identifier">add</span><span class="special">(</span> <span class="identifier">error</span><span class="special">);</span> | |
7388 | <span class="special">}</span> | |
7389 | <span class="comment">// We only arrive here when every passed function threw an exception.</span> | |
7390 | <span class="comment">// Throw our collection to inform caller.</span> | |
7391 | <span class="keyword">throw</span> <span class="identifier">exceptions</span><span class="special">;</span> | |
7392 | <span class="special">}</span> | |
7393 | </pre> | |
7394 | <p> | |
7395 | </p> | |
7396 | <p> | |
7397 | A call might look like this: | |
7398 | </p> | |
7399 | <p> | |
7400 | </p> | |
7401 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">wait_first_success</span><span class="special">(</span> | |
7402 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfss_first"</span><span class="special">,</span> <span class="number">50</span><span class="special">,</span> <span class="keyword">true</span><span class="special">);</span> <span class="special">},</span> | |
7403 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfss_second"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7404 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfss_third"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">});</span> | |
7405 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_first_success(success) => "</span> <span class="special"><<</span> <span class="identifier">result</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
7406 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">result</span> <span class="special">==</span> <span class="string">"wfss_second"</span><span class="special">);</span> | |
7407 | </pre> | |
7408 | <p> | |
7409 | </p> | |
7410 | </div> | |
7411 | <div class="section"> | |
7412 | <div class="titlepage"><div><div><h6 class="title"> | |
7413 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__heterogeneous_types"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__heterogeneous_types" title="when_any, heterogeneous types">when_any, | |
7414 | heterogeneous types</a> | |
7415 | </h6></div></div></div> | |
7416 | <p> | |
7417 | We would be remiss to ignore the case in which the various task functions | |
7418 | have distinct return types. That means that the value returned by | |
7419 | the first of them might have any one of those types. We can express | |
7420 | that with <a href="http://www.boost.org/doc/libs/release/doc/html/variant.html" target="_top">Boost.Variant</a>. | |
7421 | </p> | |
7422 | <p> | |
7423 | To keep the example simple, we'll revert to pretending that none | |
7424 | of them can throw an exception. That makes <code class="computeroutput"><span class="identifier">wait_first_value_het</span><span class="special">()</span></code> strongly resemble <a class="link" href="pooled_fixedsize.html#wait_first_value"><code class="computeroutput"><span class="identifier">wait_first_value</span><span class="special">()</span></code></a>. | |
7425 | We can actually reuse <a class="link" href="pooled_fixedsize.html#wait_first_value_impl"><code class="computeroutput"><span class="identifier">wait_first_value_impl</span><span class="special">()</span></code></a>, | |
7426 | merely passing <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">,</span> <span class="special">...></span></code> | |
7427 | as the channel's value type rather than the common <code class="computeroutput"><span class="identifier">T</span></code>! | |
7428 | </p> | |
7429 | <p> | |
7430 | Naturally this could be extended to use <a class="link" href="pooled_fixedsize.html#wait_first_success"><code class="computeroutput"><span class="identifier">wait_first_success</span><span class="special">()</span></code></a> | |
7431 | semantics instead. | |
7432 | </p> | |
7433 | <p> | |
7434 | </p> | |
7435 | <pre class="programlisting"><span class="comment">// No need to break out the first Fn for interface function: let the compiler</span> | |
7436 | <span class="comment">// complain if empty.</span> | |
7437 | <span class="comment">// Our functions have different return types, and we might have to return any</span> | |
7438 | <span class="comment">// of them. Use a variant, expanding std::result_of<Fn()>::type for each Fn in</span> | |
7439 | <span class="comment">// parameter pack.</span> | |
7440 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7441 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fns</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="special">...</span> <span class="special">></span> | |
7442 | <span class="identifier">wait_first_value_het</span><span class="special">(</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7443 | <span class="comment">// Use unbounded_channel<boost::variant<T1, T2, ...>>; see remarks above.</span> | |
7444 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fns</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="special">...</span> <span class="special">></span> <span class="identifier">return_t</span><span class="special">;</span> | |
7445 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">channel_t</span><span class="special">;</span> | |
7446 | <span class="keyword">auto</span> <span class="identifier">channelp</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">channel_t</span> <span class="special">>()</span> <span class="special">);</span> | |
7447 | <span class="comment">// launch all the relevant fibers</span> | |
7448 | <span class="identifier">wait_first_value_impl</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">>(</span> <span class="identifier">channelp</span><span class="special">,</span> | |
7449 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
7450 | <span class="comment">// retrieve the first value</span> | |
7451 | <span class="identifier">return_t</span> <span class="identifier">value</span><span class="special">(</span> <span class="identifier">channelp</span><span class="special">-></span><span class="identifier">value_pop</span><span class="special">()</span> <span class="special">);</span> | |
7452 | <span class="comment">// close the channel: no subsequent push() has to succeed</span> | |
7453 | <span class="identifier">channelp</span><span class="special">-></span><span class="identifier">close</span><span class="special">();</span> | |
7454 | <span class="keyword">return</span> <span class="identifier">value</span><span class="special">;</span> | |
7455 | <span class="special">}</span> | |
7456 | </pre> | |
7457 | <p> | |
7458 | </p> | |
7459 | <p> | |
7460 | It might be called like this: | |
7461 | </p> | |
7462 | <p> | |
7463 | </p> | |
7464 | <pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">int</span> <span class="special">></span> <span class="identifier">result</span> <span class="special">=</span> | |
7465 | <span class="identifier">wait_first_value_het</span><span class="special">(</span> | |
7466 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfvh_third"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
7467 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="number">3.14</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7468 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="number">17</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
7469 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_first_value_het() => "</span> <span class="special"><<</span> <span class="identifier">result</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
7470 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">get</span><span class="special"><</span> <span class="keyword">int</span> <span class="special">>(</span> <span class="identifier">result</span><span class="special">)</span> <span class="special">==</span> <span class="number">17</span><span class="special">);</span> | |
7471 | </pre> | |
7472 | <p> | |
7473 | </p> | |
7474 | </div> | |
7475 | <div class="section"> | |
7476 | <div class="titlepage"><div><div><h6 class="title"> | |
7477 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__a_dubious_alternative"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_any.when_any__a_dubious_alternative" title="when_any, a dubious alternative">when_any, | |
7478 | a dubious alternative</a> | |
7479 | </h6></div></div></div> | |
7480 | <p> | |
7481 | Certain topics in C++ can arouse strong passions, and exceptions | |
7482 | are no exception. We cannot resist mentioning — for purely informational | |
7483 | purposes — that when you need only the <span class="emphasis"><em>first</em></span> result | |
7484 | from some number of concurrently-running fibers, it would be possible | |
7485 | to pass a <code class="computeroutput">shared_ptr< <a class="link" href="pooled_fixedsize.html#class_promise"> <code class="computeroutput">promise<></code></a>></code> to the participating | |
7486 | fibers, then cause the initiating fiber to call <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a> on | |
7487 | its <a class="link" href="pooled_fixedsize.html#class_future"> <code class="computeroutput">future<></code></a>. The first fiber to call <a class="link" href="pooled_fixedsize.html#promise_set_value"> <code class="computeroutput">promise::set_value()</code></a> on | |
7488 | that shared <code class="computeroutput"><span class="identifier">promise</span></code> | |
7489 | will succeed; subsequent <code class="computeroutput"><span class="identifier">set_value</span><span class="special">()</span></code> calls on the same <code class="computeroutput"><span class="identifier">promise</span></code> instance will throw <code class="computeroutput"><span class="identifier">future_error</span></code>. | |
7490 | </p> | |
7491 | <p> | |
7492 | Use this information at your own discretion. Beware the dark side. | |
7493 | </p> | |
7494 | </div> | |
7495 | </div> | |
7496 | <div class="section"> | |
7497 | <div class="titlepage"><div><div><h6 class="title"> | |
7498 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality" title="when_all functionality">when_all | |
7499 | functionality</a> | |
7500 | </h6></div></div></div> | |
7501 | <div class="toc"><dl> | |
7502 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__simple_completion">when_all, | |
7503 | simple completion</a></span></dt> | |
7504 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__return_values">when_all, | |
7505 | return values</a></span></dt> | |
7506 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all_until_first_exception">when_all | |
7507 | until first exception</a></span></dt> | |
7508 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.wait_all__collecting_all_exceptions">wait_all, | |
7509 | collecting all exceptions</a></span></dt> | |
7510 | <dt><span class="section"><a href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__heterogeneous_types">when_all, | |
7511 | heterogeneous types</a></span></dt> | |
7512 | </dl></div> | |
7513 | <div class="section"> | |
7514 | <div class="titlepage"><div><div><h6 class="title"> | |
7515 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__simple_completion"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__simple_completion" title="when_all, simple completion">when_all, | |
7516 | simple completion</a> | |
7517 | </h6></div></div></div> | |
7518 | <p> | |
7519 | For the case in which we must wait for <span class="emphasis"><em>all</em></span> task | |
7520 | functions to complete — but we don't need results (or expect exceptions) | |
7521 | from any of them — we can write <code class="computeroutput"><span class="identifier">wait_all_simple</span><span class="special">()</span></code> that looks remarkably like <a class="link" href="pooled_fixedsize.html#wait_first_simple"><code class="computeroutput"><span class="identifier">wait_first_simple</span><span class="special">()</span></code></a>. The difference is that | |
7522 | instead of our <a class="link" href="pooled_fixedsize.html#wait_done"><code class="computeroutput"><span class="identifier">Done</span></code></a> | |
7523 | class, we instantiate a <a class="link" href="pooled_fixedsize.html#class_barrier"> <code class="computeroutput">barrier</code></a> and call its <a class="link" href="pooled_fixedsize.html#barrier_wait"> <code class="computeroutput">barrier::wait()</code></a>. | |
7524 | </p> | |
7525 | <p> | |
7526 | We initialize the <code class="computeroutput"><span class="identifier">barrier</span></code> | |
7527 | with <code class="computeroutput"><span class="special">(</span><span class="identifier">count</span><span class="special">+</span><span class="number">1</span><span class="special">)</span></code> because we are launching <code class="computeroutput"><span class="identifier">count</span></code> fibers, plus the <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> | |
7528 | call within <code class="computeroutput"><span class="identifier">wait_all_simple</span><span class="special">()</span></code> itself. | |
7529 | </p> | |
7530 | <p> | |
7531 | </p> | |
7532 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7533 | <span class="keyword">void</span> <span class="identifier">wait_all_simple</span><span class="special">(</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7534 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">count</span><span class="special">(</span> <span class="keyword">sizeof</span> <span class="special">...</span> <span class="special">(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">);</span> | |
7535 | <span class="comment">// Initialize a barrier(count+1) because we'll immediately wait on it. We</span> | |
7536 | <span class="comment">// don't want to wake up until 'count' more fibers wait on it. Even though</span> | |
7537 | <span class="comment">// we'll stick around until the last of them completes, use shared_ptr</span> | |
7538 | <span class="comment">// anyway because it's easier to be confident about lifespan issues.</span> | |
7539 | <span class="keyword">auto</span> <span class="identifier">barrier</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">barrier</span> <span class="special">>(</span> <span class="identifier">count</span> <span class="special">+</span> <span class="number">1</span><span class="special">)</span> <span class="special">);</span> | |
7540 | <span class="identifier">wait_all_simple_impl</span><span class="special">(</span> <span class="identifier">barrier</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
7541 | <span class="identifier">barrier</span><span class="special">-></span><span class="identifier">wait</span><span class="special">();</span> | |
7542 | <span class="special">}</span> | |
7543 | </pre> | |
7544 | <p> | |
7545 | </p> | |
7546 | <p> | |
7547 | As stated above, the only difference between <code class="computeroutput"><span class="identifier">wait_all_simple_impl</span><span class="special">()</span></code> and <a class="link" href="pooled_fixedsize.html#wait_first_simple_impl"><code class="computeroutput"><span class="identifier">wait_first_simple_impl</span><span class="special">()</span></code></a> | |
7548 | is that the former calls <code class="computeroutput"><span class="identifier">barrier</span><span class="special">::</span><span class="identifier">wait</span><span class="special">()</span></code> rather than <code class="computeroutput"><span class="identifier">Done</span><span class="special">::</span><span class="identifier">notify</span><span class="special">()</span></code>: | |
7549 | </p> | |
7550 | <p> | |
7551 | </p> | |
7552 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7553 | <span class="keyword">void</span> <span class="identifier">wait_all_simple_impl</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">barrier</span> <span class="special">></span> <span class="identifier">barrier</span><span class="special">,</span> | |
7554 | <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7555 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span><span class="special">(</span> | |
7556 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span> | |
7557 | <span class="special">[](</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">barrier</span> <span class="special">></span> <span class="special">&</span> <span class="identifier">barrier</span><span class="special">,</span> | |
7558 | <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">decay</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>::</span><span class="identifier">type</span> <span class="special">&</span> <span class="identifier">function</span><span class="special">)</span> <span class="keyword">mutable</span> <span class="special">{</span> | |
7559 | <span class="identifier">function</span><span class="special">();</span> | |
7560 | <span class="identifier">barrier</span><span class="special">-></span><span class="identifier">wait</span><span class="special">();</span> | |
7561 | <span class="special">},</span> | |
7562 | <span class="identifier">barrier</span><span class="special">,</span> | |
7563 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">)</span> | |
7564 | <span class="special">)).</span><span class="identifier">detach</span><span class="special">();</span> | |
7565 | <span class="identifier">wait_all_simple_impl</span><span class="special">(</span> <span class="identifier">barrier</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
7566 | <span class="special">}</span> | |
7567 | </pre> | |
7568 | <p> | |
7569 | </p> | |
7570 | <p> | |
7571 | You might call it like this: | |
7572 | </p> | |
7573 | <p> | |
7574 | </p> | |
7575 | <pre class="programlisting"><span class="identifier">wait_all_simple</span><span class="special">(</span> | |
7576 | <span class="special">[](){</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"was_long"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
7577 | <span class="special">[](){</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"was_medium"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7578 | <span class="special">[](){</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"was_short"</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
7579 | </pre> | |
7580 | <p> | |
7581 | </p> | |
7582 | <p> | |
7583 | Control will not return from the <code class="computeroutput"><span class="identifier">wait_all_simple</span><span class="special">()</span></code> call until the last of its task | |
7584 | functions has completed. | |
7585 | </p> | |
7586 | </div> | |
7587 | <div class="section"> | |
7588 | <div class="titlepage"><div><div><h6 class="title"> | |
7589 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__return_values"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__return_values" title="when_all, return values">when_all, | |
7590 | return values</a> | |
7591 | </h6></div></div></div> | |
7592 | <p> | |
7593 | As soon as we want to collect return values from all the task functions, | |
7594 | we can see right away how to reuse <a class="link" href="pooled_fixedsize.html#wait_first_value"><code class="computeroutput"><span class="identifier">wait_first_value</span><span class="special">()</span></code></a>'s | |
7595 | channel<T> for the purpose. All we have to do is avoid closing | |
7596 | it after the first value! | |
7597 | </p> | |
7598 | <p> | |
7599 | But in fact, collecting multiple values raises an interesting question: | |
7600 | do we <span class="emphasis"><em>really</em></span> want to wait until the slowest | |
7601 | of them has arrived? Wouldn't we rather process each result as soon | |
7602 | as it becomes available? | |
7603 | </p> | |
7604 | <p> | |
7605 | Fortunately we can present both APIs. Let's define <code class="computeroutput"><span class="identifier">wait_all_values_source</span><span class="special">()</span></code> | |
7606 | to return <code class="computeroutput"><span class="identifier">shared_ptr</span><span class="special"><</span><span class="identifier">unbounded_channel</span><span class="special"><</span><span class="identifier">T</span><span class="special">>></span></code>.<sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__return_values.f0" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__return_values.f0" class="footnote">7</a>]</sup> | |
7607 | </p> | |
7608 | <p> | |
7609 | <a name="wait_all_values"></a>Given <code class="computeroutput"><span class="identifier">wait_all_values_source</span><span class="special">()</span></code>, it's straightforward to implement | |
7610 | <code class="computeroutput"><span class="identifier">wait_all_values</span><span class="special">()</span></code>: | |
7611 | </p> | |
7612 | <p> | |
7613 | </p> | |
7614 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7615 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="special">></span> | |
7616 | <span class="identifier">wait_all_values</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7617 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">count</span><span class="special">(</span> <span class="number">1</span> <span class="special">+</span> <span class="keyword">sizeof</span> <span class="special">...</span> <span class="special">(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">);</span> | |
7618 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">return_t</span><span class="special">;</span> | |
7619 | <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">vector_t</span><span class="special">;</span> | |
7620 | <span class="identifier">vector_t</span> <span class="identifier">results</span><span class="special">;</span> | |
7621 | <span class="identifier">results</span><span class="special">.</span><span class="identifier">reserve</span><span class="special">(</span> <span class="identifier">count</span><span class="special">);</span> | |
7622 | ||
7623 | <span class="comment">// get channel</span> | |
7624 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="special">></span> <span class="identifier">channel</span> <span class="special">=</span> | |
7625 | <span class="identifier">wait_all_values_source</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">),</span> | |
7626 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
7627 | <span class="comment">// fill results vector</span> | |
7628 | <span class="identifier">return_t</span> <span class="identifier">value</span><span class="special">;</span> | |
7629 | <span class="keyword">while</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">channel_op_status</span><span class="special">::</span><span class="identifier">success</span> <span class="special">==</span> <span class="identifier">channel</span><span class="special">-></span><span class="identifier">pop</span><span class="special">(</span><span class="identifier">value</span><span class="special">)</span> <span class="special">)</span> <span class="special">{</span> | |
7630 | <span class="identifier">results</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span> <span class="identifier">value</span><span class="special">);</span> | |
7631 | <span class="special">}</span> | |
7632 | <span class="comment">// return vector to caller</span> | |
7633 | <span class="keyword">return</span> <span class="identifier">results</span><span class="special">;</span> | |
7634 | <span class="special">}</span> | |
7635 | </pre> | |
7636 | <p> | |
7637 | </p> | |
7638 | <p> | |
7639 | It might be called like this: | |
7640 | </p> | |
7641 | <p> | |
7642 | </p> | |
7643 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">values</span> <span class="special">=</span> | |
7644 | <span class="identifier">wait_all_values</span><span class="special">(</span> | |
7645 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wav_late"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
7646 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wav_middle"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7647 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wav_early"</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
7648 | </pre> | |
7649 | <p> | |
7650 | </p> | |
7651 | <p> | |
7652 | As you can see from the loop in <code class="computeroutput"><span class="identifier">wait_all_values</span><span class="special">()</span></code>, instead of requiring its caller | |
7653 | to count values, we define <code class="computeroutput"><span class="identifier">wait_all_values_source</span><span class="special">()</span></code> to <a class="link" href="pooled_fixedsize.html#unbounded_channel_close"> <code class="computeroutput">unbounded_channel::close()</code></a> the | |
7654 | channel when done. But how do we do that? Each producer fiber is | |
7655 | independent. It has no idea whether it is the last one to <a class="link" href="pooled_fixedsize.html#unbounded_channel_push"> <code class="computeroutput">unbounded_channel::push()</code></a> a | |
7656 | value. | |
7657 | </p> | |
7658 | <p> | |
7659 | <a name="wait_nchannel"></a>We can address that problem with a counting | |
7660 | façade for the <code class="computeroutput"><span class="identifier">unbounded_channel</span><span class="special"><></span></code>. In fact, our façade need | |
7661 | only support the producer end of the channel. | |
7662 | </p> | |
7663 | <p> | |
7664 | </p> | |
7665 | <pre class="programlisting"><span class="comment">// Introduce a channel facade that closes the channel once a specific number</span> | |
7666 | <span class="comment">// of items has been pushed. This allows an arbitrary consumer to read until</span> | |
7667 | <span class="comment">// 'closed' without itself having to count items.</span> | |
7668 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">></span> | |
7669 | <span class="keyword">class</span> <span class="identifier">nchannel</span> <span class="special">{</span> | |
7670 | <span class="keyword">public</span><span class="special">:</span> | |
7671 | <span class="identifier">nchannel</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">T</span> <span class="special">></span> <span class="special">></span> <span class="identifier">cp</span><span class="special">,</span> | |
7672 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">lm</span><span class="special">):</span> | |
7673 | <span class="identifier">channel_</span><span class="special">(</span> <span class="identifier">cp</span><span class="special">),</span> | |
7674 | <span class="identifier">limit_</span><span class="special">(</span> <span class="identifier">lm</span><span class="special">)</span> <span class="special">{</span> | |
7675 | <span class="identifier">assert</span><span class="special">(</span><span class="identifier">channel_</span><span class="special">);</span> | |
7676 | <span class="keyword">if</span> <span class="special">(</span> <span class="number">0</span> <span class="special">==</span> <span class="identifier">limit_</span><span class="special">)</span> <span class="special">{</span> | |
7677 | <span class="identifier">channel_</span><span class="special">-></span><span class="identifier">close</span><span class="special">();</span> | |
7678 | <span class="special">}</span> | |
7679 | <span class="special">}</span> | |
7680 | ||
7681 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">channel_op_status</span> <span class="identifier">push</span><span class="special">(</span> <span class="identifier">T</span> <span class="special">&&</span> <span class="identifier">va</span><span class="special">)</span> <span class="special">{</span> | |
7682 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">channel_op_status</span> <span class="identifier">ok</span> <span class="special">=</span> | |
7683 | <span class="identifier">channel_</span><span class="special">-></span><span class="identifier">push</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">T</span> <span class="special">>(</span> <span class="identifier">va</span><span class="special">)</span> <span class="special">);</span> | |
7684 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">ok</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">channel_op_status</span><span class="special">::</span><span class="identifier">success</span> <span class="special">&&</span> | |
7685 | <span class="special">--</span><span class="identifier">limit_</span> <span class="special">==</span> <span class="number">0</span><span class="special">)</span> <span class="special">{</span> | |
7686 | <span class="comment">// after the 'limit_'th successful push, close the channel</span> | |
7687 | <span class="identifier">channel_</span><span class="special">-></span><span class="identifier">close</span><span class="special">();</span> | |
7688 | <span class="special">}</span> | |
7689 | <span class="keyword">return</span> <span class="identifier">ok</span><span class="special">;</span> | |
7690 | <span class="special">}</span> | |
7691 | ||
7692 | <span class="keyword">private</span><span class="special">:</span> | |
7693 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">T</span> <span class="special">></span> <span class="special">></span> <span class="identifier">channel_</span><span class="special">;</span> | |
7694 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">limit_</span><span class="special">;</span> | |
7695 | <span class="special">};</span> | |
7696 | </pre> | |
7697 | <p> | |
7698 | </p> | |
7699 | <p> | |
7700 | <a name="wait_all_values_source"></a>Armed with <code class="computeroutput"><span class="identifier">nchannel</span><span class="special"><></span></code>, we can implement <code class="computeroutput"><span class="identifier">wait_all_values_source</span><span class="special">()</span></code>. | |
7701 | It starts just like <a class="link" href="pooled_fixedsize.html#wait_first_value"><code class="computeroutput"><span class="identifier">wait_first_value</span><span class="special">()</span></code></a>. | |
7702 | The difference is that we wrap the <code class="computeroutput"><span class="identifier">unbounded_channel</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> with an <code class="computeroutput"><span class="identifier">nchannel</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> to pass to the producer fibers. | |
7703 | </p> | |
7704 | <p> | |
7705 | Then, of course, instead of popping the first value, closing the | |
7706 | channel and returning it, we simply return the <code class="computeroutput"><span class="identifier">shared_ptr</span><span class="special"><</span><span class="identifier">unbounded_channel</span><span class="special"><</span><span class="identifier">T</span><span class="special">>></span></code>. | |
7707 | </p> | |
7708 | <p> | |
7709 | </p> | |
7710 | <pre class="programlisting"><span class="comment">// Return a shared_ptr<unbounded_channel<T>> from which the caller can</span> | |
7711 | <span class="comment">// retrieve each new result as it arrives, until 'closed'.</span> | |
7712 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7713 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="special">></span> <span class="special">></span> | |
7714 | <span class="identifier">wait_all_values_source</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7715 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">count</span><span class="special">(</span> <span class="number">1</span> <span class="special">+</span> <span class="keyword">sizeof</span> <span class="special">...</span> <span class="special">(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">);</span> | |
7716 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">return_t</span><span class="special">;</span> | |
7717 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">channel_t</span><span class="special">;</span> | |
7718 | <span class="comment">// make the channel</span> | |
7719 | <span class="keyword">auto</span> <span class="identifier">channelp</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">channel_t</span> <span class="special">>()</span> <span class="special">);</span> | |
7720 | <span class="comment">// and make an nchannel facade to close it after 'count' items</span> | |
7721 | <span class="keyword">auto</span> <span class="identifier">ncp</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">nchannel</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="special">>(</span> <span class="identifier">channelp</span><span class="special">,</span> <span class="identifier">count</span><span class="special">)</span> <span class="special">);</span> | |
7722 | <span class="comment">// pass that nchannel facade to all the relevant fibers</span> | |
7723 | <span class="identifier">wait_all_values_impl</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">>(</span> <span class="identifier">ncp</span><span class="special">,</span> | |
7724 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">),</span> | |
7725 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
7726 | <span class="comment">// then return the channel for consumer</span> | |
7727 | <span class="keyword">return</span> <span class="identifier">channelp</span><span class="special">;</span> | |
7728 | <span class="special">}</span> | |
7729 | </pre> | |
7730 | <p> | |
7731 | </p> | |
7732 | <p> | |
7733 | For example: | |
7734 | </p> | |
7735 | <p> | |
7736 | </p> | |
7737 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="special">></span> <span class="identifier">channel</span> <span class="special">=</span> | |
7738 | <span class="identifier">wait_all_values_source</span><span class="special">(</span> | |
7739 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wavs_third"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
7740 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wavs_second"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7741 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wavs_first"</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
7742 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">value</span><span class="special">;</span> | |
7743 | <span class="keyword">while</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">channel_op_status</span><span class="special">::</span><span class="identifier">success</span> <span class="special">==</span> <span class="identifier">channel</span><span class="special">-></span><span class="identifier">pop</span><span class="special">(</span><span class="identifier">value</span><span class="special">)</span> <span class="special">)</span> <span class="special">{</span> | |
7744 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_all_values_source() => '"</span> <span class="special"><<</span> <span class="identifier">value</span> | |
7745 | <span class="special"><<</span> <span class="string">"'"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
7746 | <span class="special">}</span> | |
7747 | </pre> | |
7748 | <p> | |
7749 | </p> | |
7750 | <p> | |
7751 | <a name="wait_all_values_impl"></a><code class="computeroutput"><span class="identifier">wait_all_values_impl</span><span class="special">()</span></code> really is just like <a class="link" href="pooled_fixedsize.html#wait_first_value_impl"><code class="computeroutput"><span class="identifier">wait_first_value_impl</span><span class="special">()</span></code></a> | |
7752 | except for the use of <code class="computeroutput"><span class="identifier">nchannel</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> rather than <code class="computeroutput"><span class="identifier">unbounded_channel</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>: | |
7753 | </p> | |
7754 | <p> | |
7755 | </p> | |
7756 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Fn</span> <span class="special">></span> | |
7757 | <span class="keyword">void</span> <span class="identifier">wait_all_values_impl</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">nchannel</span><span class="special"><</span> <span class="identifier">T</span> <span class="special">></span> <span class="special">></span> <span class="identifier">channel</span><span class="special">,</span> | |
7758 | <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">)</span> <span class="special">{</span> | |
7759 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span><span class="special">(</span> <span class="special">[</span><span class="identifier">channel</span><span class="special">,</span> <span class="identifier">function</span><span class="special">](){</span> | |
7760 | <span class="identifier">channel</span><span class="special">-></span><span class="identifier">push</span><span class="special">(</span><span class="identifier">function</span><span class="special">());</span> | |
7761 | <span class="special">}).</span><span class="identifier">detach</span><span class="special">();</span> | |
7762 | <span class="special">}</span> | |
7763 | </pre> | |
7764 | <p> | |
7765 | </p> | |
7766 | </div> | |
7767 | <div class="section"> | |
7768 | <div class="titlepage"><div><div><h6 class="title"> | |
7769 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all_until_first_exception"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all_until_first_exception" title="when_all until first exception">when_all | |
7770 | until first exception</a> | |
7771 | </h6></div></div></div> | |
7772 | <p> | |
7773 | Naturally, just as with <a class="link" href="pooled_fixedsize.html#wait_first_outcome"><code class="computeroutput"><span class="identifier">wait_first_outcome</span><span class="special">()</span></code></a>, | |
7774 | we can elaborate <a class="link" href="pooled_fixedsize.html#wait_all_values"><code class="computeroutput"><span class="identifier">wait_all_values</span><span class="special">()</span></code></a> and <a class="link" href="pooled_fixedsize.html#wait_all_values_source"><code class="computeroutput"><span class="identifier">wait_all_values_source</span><span class="special">()</span></code></a> | |
7775 | by passing <code class="computeroutput"><span class="identifier">future</span><span class="special"><</span> <span class="identifier">T</span> | |
7776 | <span class="special">></span></code> instead of plain <code class="computeroutput"><span class="identifier">T</span></code>. | |
7777 | </p> | |
7778 | <p> | |
7779 | <a name="wait_all_until_error"></a><code class="computeroutput"><span class="identifier">wait_all_until_error</span><span class="special">()</span></code> pops that <code class="computeroutput"><span class="identifier">future</span><span class="special"><</span> <span class="identifier">T</span> | |
7780 | <span class="special">></span></code> and calls its <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a>: | |
7781 | </p> | |
7782 | <p> | |
7783 | </p> | |
7784 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7785 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="special">></span> | |
7786 | <span class="identifier">wait_all_until_error</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7787 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">count</span><span class="special">(</span> <span class="number">1</span> <span class="special">+</span> <span class="keyword">sizeof</span> <span class="special">...</span> <span class="special">(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">);</span> | |
7788 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">return_t</span><span class="special">;</span> | |
7789 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">future_t</span><span class="special">;</span> | |
7790 | <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">vector_t</span><span class="special">;</span> | |
7791 | <span class="identifier">vector_t</span> <span class="identifier">results</span><span class="special">;</span> | |
7792 | <span class="identifier">results</span><span class="special">.</span><span class="identifier">reserve</span><span class="special">(</span> <span class="identifier">count</span><span class="special">);</span> | |
7793 | ||
7794 | <span class="comment">// get channel</span> | |
7795 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> | |
7796 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">future_t</span> <span class="special">></span> <span class="special">></span> <span class="identifier">channel</span><span class="special">(</span> | |
7797 | <span class="identifier">wait_all_until_error_source</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">),</span> | |
7798 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">)</span> <span class="special">);</span> | |
7799 | <span class="comment">// fill results vector</span> | |
7800 | <span class="identifier">future_t</span> <span class="identifier">future</span><span class="special">;</span> | |
7801 | <span class="keyword">while</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">channel_op_status</span><span class="special">::</span><span class="identifier">success</span> <span class="special">==</span> <span class="identifier">channel</span><span class="special">-></span><span class="identifier">pop</span><span class="special">(</span> <span class="identifier">future</span><span class="special">)</span> <span class="special">)</span> <span class="special">{</span> | |
7802 | <span class="identifier">results</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="special">);</span> | |
7803 | <span class="special">}</span> | |
7804 | <span class="comment">// return vector to caller</span> | |
7805 | <span class="keyword">return</span> <span class="identifier">results</span><span class="special">;</span> | |
7806 | <span class="special">}</span> | |
7807 | </pre> | |
7808 | <p> | |
7809 | </p> | |
7810 | <p> | |
7811 | For example: | |
7812 | </p> | |
7813 | <p> | |
7814 | </p> | |
7815 | <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">thrown</span><span class="special">;</span> | |
7816 | <span class="keyword">try</span> <span class="special">{</span> | |
7817 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">values</span> <span class="special">=</span> <span class="identifier">wait_all_until_error</span><span class="special">(</span> | |
7818 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"waue_late"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
7819 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"waue_middle"</span><span class="special">,</span> <span class="number">100</span><span class="special">,</span> <span class="keyword">true</span><span class="special">);</span> <span class="special">},</span> | |
7820 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"waue_early"</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
7821 | <span class="special">}</span> <span class="keyword">catch</span> <span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">e</span><span class="special">)</span> <span class="special">{</span> | |
7822 | <span class="identifier">thrown</span> <span class="special">=</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">();</span> | |
7823 | <span class="special">}</span> | |
7824 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_all_until_error(fail) threw '"</span> <span class="special"><<</span> <span class="identifier">thrown</span> | |
7825 | <span class="special"><<</span> <span class="string">"'"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
7826 | </pre> | |
7827 | <p> | |
7828 | </p> | |
7829 | <p> | |
7830 | <a name="wait_all_until_error_source"></a>Naturally this complicates | |
7831 | the API for <code class="computeroutput"><span class="identifier">wait_all_until_error_source</span><span class="special">()</span></code>. The caller must both retrieve | |
7832 | a <code class="computeroutput"><span class="identifier">future</span><span class="special"><</span> | |
7833 | <span class="identifier">T</span> <span class="special">></span></code> | |
7834 | and call its <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code> method. It would, of course, be | |
7835 | possible to return a façade over the consumer end of the channel | |
7836 | that would implicitly perform the <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code> and return a simple <code class="computeroutput"><span class="identifier">T</span></code> (or throw). | |
7837 | </p> | |
7838 | <p> | |
7839 | The implementation is just as you would expect. Notice, however, | |
7840 | that we can reuse <a class="link" href="pooled_fixedsize.html#wait_first_outcome_impl"><code class="computeroutput"><span class="identifier">wait_first_outcome_impl</span><span class="special">()</span></code></a>, | |
7841 | passing the <code class="computeroutput"><span class="identifier">nchannel</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> rather than <code class="computeroutput"><span class="identifier">unbounded_channel</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>. | |
7842 | </p> | |
7843 | <p> | |
7844 | </p> | |
7845 | <pre class="programlisting"><span class="comment">// Return a shared_ptr<unbounded_channel<future<T>>> from which the caller can</span> | |
7846 | <span class="comment">// get() each new result as it arrives, until 'closed'.</span> | |
7847 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7848 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> | |
7849 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> | |
7850 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> | |
7851 | <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="special">></span> <span class="special">></span> <span class="special">></span> | |
7852 | <span class="identifier">wait_all_until_error_source</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7853 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">count</span><span class="special">(</span> <span class="number">1</span> <span class="special">+</span> <span class="keyword">sizeof</span> <span class="special">...</span> <span class="special">(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">);</span> | |
7854 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">return_t</span><span class="special">;</span> | |
7855 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">future_t</span><span class="special">;</span> | |
7856 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">future_t</span> <span class="special">></span> <span class="identifier">channel_t</span><span class="special">;</span> | |
7857 | <span class="comment">// make the channel</span> | |
7858 | <span class="keyword">auto</span> <span class="identifier">channelp</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">channel_t</span> <span class="special">>()</span> <span class="special">);</span> | |
7859 | <span class="comment">// and make an nchannel facade to close it after 'count' items</span> | |
7860 | <span class="keyword">auto</span> <span class="identifier">ncp</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special"><</span> <span class="identifier">nchannel</span><span class="special"><</span> <span class="identifier">future_t</span> <span class="special">></span> <span class="special">>(</span> <span class="identifier">channelp</span><span class="special">,</span> <span class="identifier">count</span><span class="special">)</span> <span class="special">);</span> | |
7861 | <span class="comment">// pass that nchannel facade to all the relevant fibers</span> | |
7862 | <span class="identifier">wait_first_outcome_impl</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">>(</span> <span class="identifier">ncp</span><span class="special">,</span> | |
7863 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">),</span> | |
7864 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
7865 | <span class="comment">// then return the channel for consumer</span> | |
7866 | <span class="keyword">return</span> <span class="identifier">channelp</span><span class="special">;</span> | |
7867 | <span class="special">}</span> | |
7868 | </pre> | |
7869 | <p> | |
7870 | </p> | |
7871 | <p> | |
7872 | For example: | |
7873 | </p> | |
7874 | <p> | |
7875 | </p> | |
7876 | <pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="identifier">future_t</span><span class="special">;</span> | |
7877 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">future_t</span> <span class="special">></span> <span class="special">></span> <span class="identifier">channel</span> <span class="special">=</span> | |
7878 | <span class="identifier">wait_all_until_error_source</span><span class="special">(</span> | |
7879 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wauess_third"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
7880 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wauess_second"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7881 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wauess_first"</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
7882 | <span class="identifier">future_t</span> <span class="identifier">future</span><span class="special">;</span> | |
7883 | <span class="keyword">while</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">channel_op_status</span><span class="special">::</span><span class="identifier">success</span> <span class="special">==</span> <span class="identifier">channel</span><span class="special">-></span><span class="identifier">pop</span><span class="special">(</span> <span class="identifier">future</span><span class="special">)</span> <span class="special">)</span> <span class="special">{</span> | |
7884 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">value</span><span class="special">(</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="special">);</span> | |
7885 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_all_until_error_source(success) => '"</span> <span class="special"><<</span> <span class="identifier">value</span> | |
7886 | <span class="special"><<</span> <span class="string">"'"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
7887 | <span class="special">}</span> | |
7888 | </pre> | |
7889 | <p> | |
7890 | </p> | |
7891 | </div> | |
7892 | <div class="section"> | |
7893 | <div class="titlepage"><div><div><h6 class="title"> | |
7894 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.wait_all__collecting_all_exceptions"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.wait_all__collecting_all_exceptions" title="wait_all, collecting all exceptions">wait_all, | |
7895 | collecting all exceptions</a> | |
7896 | </h6></div></div></div> | |
7897 | <p> | |
7898 | <a name="wait_all_collect_errors"></a>Given <a class="link" href="pooled_fixedsize.html#wait_all_until_error_source"><code class="computeroutput"><span class="identifier">wait_all_until_error_source</span><span class="special">()</span></code></a>, | |
7899 | it might be more reasonable to make a <code class="computeroutput"><span class="identifier">wait_all_</span><span class="special">...()</span></code> that collects <span class="emphasis"><em>all</em></span> | |
7900 | errors instead of presenting only the first: | |
7901 | </p> | |
7902 | <p> | |
7903 | </p> | |
7904 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7905 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="special">></span> | |
7906 | <span class="identifier">wait_all_collect_errors</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">function</span><span class="special">,</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7907 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">count</span><span class="special">(</span> <span class="number">1</span> <span class="special">+</span> <span class="keyword">sizeof</span> <span class="special">...</span> <span class="special">(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">);</span> | |
7908 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special"><</span> <span class="identifier">Fn</span><span class="special">()</span> <span class="special">>::</span><span class="identifier">type</span> <span class="identifier">return_t</span><span class="special">;</span> | |
7909 | <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">future</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">future_t</span><span class="special">;</span> | |
7910 | <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="identifier">return_t</span> <span class="special">></span> <span class="identifier">vector_t</span><span class="special">;</span> | |
7911 | <span class="identifier">vector_t</span> <span class="identifier">results</span><span class="special">;</span> | |
7912 | <span class="identifier">results</span><span class="special">.</span><span class="identifier">reserve</span><span class="special">(</span> <span class="identifier">count</span><span class="special">);</span> | |
7913 | <span class="identifier">exception_list</span> <span class="identifier">exceptions</span><span class="special">(</span><span class="string">"wait_all_collect_errors() exceptions"</span><span class="special">);</span> | |
7914 | ||
7915 | <span class="comment">// get channel</span> | |
7916 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special"><</span> | |
7917 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">unbounded_channel</span><span class="special"><</span> <span class="identifier">future_t</span> <span class="special">></span> <span class="special">></span> <span class="identifier">channel</span><span class="special">(</span> | |
7918 | <span class="identifier">wait_all_until_error_source</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fn</span> <span class="special">>(</span> <span class="identifier">function</span><span class="special">),</span> | |
7919 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">)</span> <span class="special">);</span> | |
7920 | <span class="comment">// fill results and/or exceptions vectors</span> | |
7921 | <span class="identifier">future_t</span> <span class="identifier">future</span><span class="special">;</span> | |
7922 | <span class="keyword">while</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">channel_op_status</span><span class="special">::</span><span class="identifier">success</span> <span class="special">==</span> <span class="identifier">channel</span><span class="special">-></span><span class="identifier">pop</span><span class="special">(</span> <span class="identifier">future</span><span class="special">)</span> <span class="special">)</span> <span class="special">{</span> | |
7923 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span> <span class="identifier">exp</span> <span class="special">=</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get_exception_ptr</span><span class="special">();</span> | |
7924 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">exp</span><span class="special">)</span> <span class="special">{</span> | |
7925 | <span class="identifier">results</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span> <span class="identifier">future</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="special">);</span> | |
7926 | <span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span> | |
7927 | <span class="identifier">exceptions</span><span class="special">.</span><span class="identifier">add</span><span class="special">(</span> <span class="identifier">exp</span><span class="special">);</span> | |
7928 | <span class="special">}</span> | |
7929 | <span class="special">}</span> | |
7930 | <span class="comment">// if there were any exceptions, throw</span> | |
7931 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">exceptions</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> | |
7932 | <span class="keyword">throw</span> <span class="identifier">exceptions</span><span class="special">;</span> | |
7933 | <span class="special">}</span> | |
7934 | <span class="comment">// no exceptions: return vector to caller</span> | |
7935 | <span class="keyword">return</span> <span class="identifier">results</span><span class="special">;</span> | |
7936 | <span class="special">}</span> | |
7937 | </pre> | |
7938 | <p> | |
7939 | </p> | |
7940 | <p> | |
7941 | The implementation is a simple variation on <a class="link" href="pooled_fixedsize.html#wait_first_success"><code class="computeroutput"><span class="identifier">wait_first_success</span><span class="special">()</span></code></a>, | |
7942 | using the same <a class="link" href="pooled_fixedsize.html#exception_list"><code class="computeroutput"><span class="identifier">exception_list</span></code></a> | |
7943 | exception class. | |
7944 | </p> | |
7945 | </div> | |
7946 | <div class="section"> | |
7947 | <div class="titlepage"><div><div><h6 class="title"> | |
7948 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__heterogeneous_types"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__heterogeneous_types" title="when_all, heterogeneous types">when_all, | |
7949 | heterogeneous types</a> | |
7950 | </h6></div></div></div> | |
7951 | <p> | |
7952 | But what about the case when we must wait for all results of different | |
7953 | types? | |
7954 | </p> | |
7955 | <p> | |
7956 | We can present an API that is frankly quite cool. Consider a sample | |
7957 | struct: | |
7958 | </p> | |
7959 | <p> | |
7960 | </p> | |
7961 | <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Data</span> <span class="special">{</span> | |
7962 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">str</span><span class="special">;</span> | |
7963 | <span class="keyword">double</span> <span class="identifier">inexact</span><span class="special">;</span> | |
7964 | <span class="keyword">int</span> <span class="identifier">exact</span><span class="special">;</span> | |
7965 | ||
7966 | <span class="keyword">friend</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&</span> <span class="keyword">operator</span><span class="special"><<(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&</span> <span class="identifier">out</span><span class="special">,</span> <span class="identifier">Data</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">data</span><span class="special">);</span> | |
7967 | <span class="special">...</span> | |
7968 | <span class="special">};</span> | |
7969 | </pre> | |
7970 | <p> | |
7971 | </p> | |
7972 | <p> | |
7973 | Let's fill its members from task functions all running concurrently: | |
7974 | </p> | |
7975 | <p> | |
7976 | </p> | |
7977 | <pre class="programlisting"><span class="identifier">Data</span> <span class="identifier">data</span> <span class="special">=</span> <span class="identifier">wait_all_members</span><span class="special"><</span> <span class="identifier">Data</span> <span class="special">>(</span> | |
7978 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wams_left"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
7979 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="number">3.14</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
7980 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="number">17</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
7981 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_all_members<Data>(success) => "</span> <span class="special"><<</span> <span class="identifier">data</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
7982 | </pre> | |
7983 | <p> | |
7984 | </p> | |
7985 | <p> | |
7986 | Note that for this case, we abandon the notion of capturing the earliest | |
7987 | result first, and so on: we must fill exactly the passed struct in | |
7988 | left-to-right order. | |
7989 | </p> | |
7990 | <p> | |
7991 | That permits a beautifully simple implementation: | |
7992 | </p> | |
7993 | <p> | |
7994 | </p> | |
7995 | <pre class="programlisting"><span class="comment">// Explicitly pass Result. This can be any type capable of being initialized</span> | |
7996 | <span class="comment">// from the results of the passed functions, such as a struct.</span> | |
7997 | <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Result</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">></span> | |
7998 | <span class="identifier">Result</span> <span class="identifier">wait_all_members</span><span class="special">(</span> <span class="identifier">Fns</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span> | |
7999 | <span class="comment">// Run each of the passed functions on a separate fiber, passing all their</span> | |
8000 | <span class="comment">// futures to helper function for processing.</span> | |
8001 | <span class="keyword">return</span> <span class="identifier">wait_all_members_get</span><span class="special"><</span> <span class="identifier">Result</span> <span class="special">>(</span> | |
8002 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">async</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span> <span class="identifier">Fns</span> <span class="special">>(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">)</span> <span class="special">...</span> <span class="special">);</span> | |
8003 | <span class="special">}</span> | |
8004 | </pre> | |
8005 | <p> | |
8006 | </p> | |
8007 | <p> | |
8008 | </p> | |
8009 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Result</span><span class="special">,</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Futures</span> <span class="special">></span> | |
8010 | <span class="identifier">Result</span> <span class="identifier">wait_all_members_get</span><span class="special">(</span> <span class="identifier">Futures</span> <span class="special">&&</span> <span class="special">...</span> <span class="identifier">futures</span><span class="special">)</span> <span class="special">{</span> | |
8011 | <span class="comment">// Fetch the results from the passed futures into Result's initializer</span> | |
8012 | <span class="comment">// list. It's true that the get() calls here will block the implicit</span> | |
8013 | <span class="comment">// iteration over futures -- but that doesn't matter because we won't be</span> | |
8014 | <span class="comment">// done until the slowest of them finishes anyway. As results are</span> | |
8015 | <span class="comment">// processed in argument-list order rather than order of completion, the</span> | |
8016 | <span class="comment">// leftmost get() to throw an exception will cause that exception to</span> | |
8017 | <span class="comment">// propagate to the caller.</span> | |
8018 | <span class="keyword">return</span> <span class="identifier">Result</span><span class="special">{</span> <span class="identifier">futures</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="special">...</span> <span class="special">};</span> | |
8019 | <span class="special">}</span> | |
8020 | </pre> | |
8021 | <p> | |
8022 | </p> | |
8023 | <p> | |
8024 | It is tempting to try to implement <code class="computeroutput"><span class="identifier">wait_all_members</span><span class="special">()</span></code> as a one-liner like this: | |
8025 | </p> | |
8026 | <pre class="programlisting"><span class="keyword">return</span> <span class="identifier">Result</span><span class="special">{</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">async</span><span class="special">(</span><span class="identifier">functions</span><span class="special">).</span><span class="identifier">get</span><span class="special">()...</span> <span class="special">};</span> | |
8027 | </pre> | |
8028 | <p> | |
8029 | The trouble with this tactic is that it would serialize all the task | |
8030 | functions. The runtime makes a single pass through <code class="computeroutput"><span class="identifier">functions</span></code>, calling <a class="link" href="pooled_fixedsize.html#fibers_async"> <code class="computeroutput">fibers::async()</code></a> for | |
8031 | each and then immediately calling <a class="link" href="pooled_fixedsize.html#future_get"> <code class="computeroutput">future::get()</code></a> on its returned | |
8032 | <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code>. | |
8033 | That blocks the implicit loop. The above is almost equivalent to | |
8034 | writing: | |
8035 | </p> | |
8036 | <pre class="programlisting"><span class="keyword">return</span> <span class="identifier">Result</span><span class="special">{</span> <span class="identifier">functions</span><span class="special">()...</span> <span class="special">};</span> | |
8037 | </pre> | |
8038 | <p> | |
8039 | in which, of course, there is no concurrency at all. | |
8040 | </p> | |
8041 | <p> | |
8042 | Passing the argument pack through a function-call boundary (<code class="computeroutput"><span class="identifier">wait_all_members_get</span><span class="special">()</span></code>) | |
8043 | forces the runtime to make <span class="emphasis"><em>two</em></span> passes: one in | |
8044 | <code class="computeroutput"><span class="identifier">wait_all_members</span><span class="special">()</span></code> to collect the <code class="computeroutput"><span class="identifier">future</span><span class="special"><></span></code>s from all the <code class="computeroutput"><span class="identifier">async</span><span class="special">()</span></code> | |
8045 | calls, the second in <code class="computeroutput"><span class="identifier">wait_all_members_get</span><span class="special">()</span></code> to fetch each of the results. | |
8046 | </p> | |
8047 | <p> | |
8048 | As noted in comments, within the <code class="computeroutput"><span class="identifier">wait_all_members_get</span><span class="special">()</span></code> parameter pack expansion pass, | |
8049 | the blocking behavior of <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code> becomes irrelevant. Along the way, | |
8050 | we will hit the <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code> for the slowest task function; | |
8051 | after that every subsequent <code class="computeroutput"><span class="identifier">get</span><span class="special">()</span></code> will complete in trivial time. | |
8052 | </p> | |
8053 | <p> | |
8054 | By the way, we could also use this same API to fill a vector or other | |
8055 | collection: | |
8056 | </p> | |
8057 | <p> | |
8058 | </p> | |
8059 | <pre class="programlisting"><span class="comment">// If we don't care about obtaining results as soon as they arrive, and we</span> | |
8060 | <span class="comment">// prefer a result vector in passed argument order rather than completion</span> | |
8061 | <span class="comment">// order, wait_all_members() is another possible implementation of</span> | |
8062 | <span class="comment">// wait_all_until_error().</span> | |
8063 | <span class="keyword">auto</span> <span class="identifier">strings</span> <span class="special">=</span> <span class="identifier">wait_all_members</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">></span> <span class="special">>(</span> | |
8064 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wamv_left"</span><span class="special">,</span> <span class="number">150</span><span class="special">);</span> <span class="special">},</span> | |
8065 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wamv_middle"</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> <span class="special">},</span> | |
8066 | <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wamv_right"</span><span class="special">,</span> <span class="number">50</span><span class="special">);</span> <span class="special">});</span> | |
8067 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"wait_all_members<vector>() =>"</span><span class="special">;</span> | |
8068 | <span class="keyword">for</span> <span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">str</span> <span class="special">:</span> <span class="identifier">strings</span><span class="special">)</span> <span class="special">{</span> | |
8069 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">" '"</span> <span class="special"><<</span> <span class="identifier">str</span> <span class="special"><<</span> <span class="string">"'"</span><span class="special">;</span> | |
8070 | <span class="special">}</span> | |
8071 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> | |
8072 | </pre> | |
8073 | <p> | |
8074 | </p> | |
8075 | </div> | |
8076 | </div> | |
8077 | </div> | |
8078 | <div class="section"> | |
8079 | <div class="titlepage"><div><div><h5 class="title"> | |
8080 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.integration"></a><a name="integration"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.integration" title="Sharing a Thread with Another Main Loop">Sharing | |
8081 | a Thread with Another Main Loop</a> | |
8082 | </h5></div></div></div> | |
8083 | <h6> | |
8084 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.integration.h0"></a> | |
8085 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.integration.overview"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.integration.overview">Overview</a> | |
8086 | </h6> | |
8087 | <p> | |
8088 | As always with cooperative concurrency, it is important not to let any | |
8089 | one fiber monopolize the processor too long: that could <span class="quote">“<span class="quote">starve</span>”</span> | |
8090 | other ready fibers. This section discusses a couple of solutions. | |
8091 | </p> | |
8092 | <h6> | |
8093 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.integration.h1"></a> | |
8094 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.integration.event_driven_program"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.integration.event_driven_program">Event-Driven | |
8095 | Program</a> | |
8096 | </h6> | |
8097 | <p> | |
8098 | Consider a classic event-driven program, organized around a main loop | |
8099 | that fetches and dispatches incoming I/O events. You are introducing | |
8100 | <span class="bold"><strong>Boost.Fiber</strong></span> because certain asynchronous | |
8101 | I/O sequences are logically sequential, and for those you want to write | |
8102 | and maintain code that looks and acts sequential. | |
8103 | </p> | |
8104 | <p> | |
8105 | You are launching fibers on the application's main thread because certain | |
8106 | of their actions will affect its user interface, and the application's | |
8107 | UI framework permits UI operations only on the main thread. Or perhaps | |
8108 | those fibers need access to main-thread data, and it would be too expensive | |
8109 | in runtime (or development time) to robustly defend every such data item | |
8110 | with thread synchronization primitives. | |
8111 | </p> | |
8112 | <p> | |
8113 | You must ensure that the application's main loop <span class="emphasis"><em>itself</em></span> | |
8114 | doesn't monopolize the processor: that the fibers it launches will get | |
8115 | the CPU cycles they need. | |
8116 | </p> | |
8117 | <p> | |
8118 | The solution is the same as for any fiber that might claim the CPU for | |
8119 | an extended time: introduce calls to <a class="link" href="../../fiber_mgmt/this_fiber.html#this_fiber_yield"> <code class="computeroutput">this_fiber::yield()</code></a>. | |
8120 | The most straightforward approach is to call <code class="computeroutput"><span class="identifier">yield</span><span class="special">()</span></code> on every iteration of your existing | |
8121 | main loop. In effect, this unifies the application's main loop with | |
8122 | <span class="bold"><strong>Boost.Fiber</strong></span>'s internal main loop. <code class="computeroutput"><span class="identifier">yield</span><span class="special">()</span></code> | |
8123 | allows the fiber manager to run any fibers that have become ready since | |
8124 | the previous iteration of the application's main loop. When these fibers | |
8125 | have had a turn, control passes to the thread's main fiber, which returns | |
8126 | from <code class="computeroutput"><span class="identifier">yield</span><span class="special">()</span></code> | |
8127 | and resumes the application's main loop. | |
8128 | </p> | |
8129 | <h6> | |
8130 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.integration.h2"></a> | |
8131 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.integration.integrating_with__ulink_url__http___www_boost_org_doc_libs_release_libs_asio_index_html__boost_asio__ulink_"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.integration.integrating_with__ulink_url__http___www_boost_org_doc_libs_release_libs_asio_index_html__boost_asio__ulink_">Integrating | |
8132 | with <a href="http://www.boost.org/doc/libs/release/libs/asio/index.html" target="_top">Boost.Asio</a></a> | |
8133 | </h6> | |
8134 | <p> | |
8135 | More challenging is when the application's main loop is embedded in some | |
8136 | other library or framework. Such an application will typically, after | |
8137 | performing all necessary setup, pass control to some form of <code class="computeroutput"><span class="identifier">run</span><span class="special">()</span></code> | |
8138 | function from which control does not return until application shutdown. | |
8139 | </p> | |
8140 | <p> | |
8141 | A <a href="http://www.boost.org/doc/libs/release/libs/asio/index.html" target="_top">Boost.Asio</a> | |
8142 | program might call <a href="http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service/run.html" target="_top"><code class="computeroutput"><span class="identifier">io_service</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code></a> | |
8143 | in this way. | |
8144 | </p> | |
8145 | <p> | |
8146 | The trick here is to arrange to pass control to <a class="link" href="../../fiber_mgmt/this_fiber.html#this_fiber_yield"> <code class="computeroutput">this_fiber::yield()</code></a> frequently. | |
8147 | You can use an <a href="http://www.boost.org/doc/libs/1_59_0/doc/html/boost_asio/reference/high_resolution_timer.html" target="_top">Asio | |
8148 | timer</a> for this purpose. Instantiate the timer, arranging to call | |
8149 | a handler function when the timer expires: | |
8150 | </p> | |
8151 | <p> | |
8152 | [run_service] | |
8153 | </p> | |
8154 | <p> | |
8155 | The handler function calls <code class="computeroutput"><span class="identifier">yield</span><span class="special">()</span></code>, then resets the timer and arranges | |
8156 | to wake up again on expiration: | |
8157 | </p> | |
8158 | <p> | |
8159 | [timer_handler] | |
8160 | </p> | |
8161 | <p> | |
8162 | Then instead of directly calling <code class="computeroutput"><span class="identifier">io_service</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code>, your application would call the above | |
8163 | <code class="computeroutput"><span class="identifier">run_service</span><span class="special">(</span><span class="identifier">io_service</span><span class="special">&)</span></code> | |
8164 | wrapper. | |
8165 | </p> | |
8166 | <p> | |
8167 | Since, in this example, we always pass control to the fiber manager via | |
8168 | <code class="computeroutput"><span class="identifier">yield</span><span class="special">()</span></code>, | |
8169 | the calling fiber is never blocked. Therefore there is always at least | |
8170 | one ready fiber. Therefore the fiber manager never sleeps. | |
8171 | </p> | |
8172 | <p> | |
8173 | Using <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="number">0</span><span class="special">)</span></code> for | |
8174 | <span class="emphasis"><em>every</em></span> keepalive timer interval would be unfriendly | |
8175 | to other threads. When all I/O is pending and all fibers are blocked, | |
8176 | the io_service and the fiber manager would simply spin the CPU, passing | |
8177 | control back and forth to each other. Resetting the timer for <code class="computeroutput"><span class="identifier">keepalive_iterval</span></code> allows tuning the | |
8178 | responsiveness of this thread relative to others in the same way as when | |
8179 | <span class="bold"><strong>Boost.Fiber</strong></span> is running without <a href="http://www.boost.org/doc/libs/release/libs/asio/index.html" target="_top">Boost.Asio</a>. | |
8180 | </p> | |
8181 | <p> | |
8182 | The source code above is found in <a href="../../../../../examples/asio/round_robin.hpp" target="_top">round_robin.hpp</a>. | |
8183 | </p> | |
8184 | </div> | |
8185 | <div class="section"> | |
8186 | <div class="titlepage"><div><div><h5 class="title"> | |
8187 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.performance" title="Performance">Performance</a> | |
8188 | </h5></div></div></div> | |
8189 | <p> | |
8190 | Performance measurements were taken using <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">highresolution_clock</span></code>, | |
8191 | with overhead corrections. The code was compiled using the build options: | |
8192 | variant = release, optimization = speed <sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance.f0" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.performance.f0" class="footnote">8</a>]</sup>. | |
8193 | </p> | |
8194 | <p> | |
8195 | The columns labeled <span class="bold"><strong>fiber (atomics)</strong></span> | |
8196 | were compiled with default fiber synchronization, capable of synchronizing | |
8197 | fibers running on different threads. The columns labeled <span class="bold"><strong>fiber | |
8198 | (raw)</strong></span> were compiled with <a class="link" href="../../overview.html#cross_thread_sync"><code class="computeroutput"><span class="identifier">BOOST_FIBERS_NO_ATOMICS</span></code></a>. | |
8199 | </p> | |
8200 | <div class="table"> | |
8201 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance.overhead_of_join__contains_fiber_context_destruction__fiber_stack_deallocation_"></a><p class="title"><b>Table 1.1. Overhead of join (contains fiber-context destruction, fiber-stack | |
8202 | deallocation)</b></p> | |
8203 | <div class="table-contents"><table class="table" summary="Overhead of join (contains fiber-context destruction, fiber-stack | |
8204 | deallocation)"> | |
8205 | <colgroup> | |
8206 | <col> | |
8207 | <col> | |
8208 | <col> | |
8209 | <col> | |
8210 | <col> | |
8211 | </colgroup> | |
8212 | <thead><tr> | |
8213 | <th> | |
8214 | <p> | |
8215 | thread | |
8216 | </p> | |
8217 | </th> | |
8218 | <th> | |
8219 | <p> | |
8220 | fiber (atomics) | |
8221 | </p> | |
8222 | </th> | |
8223 | <th> | |
8224 | <p> | |
8225 | fiber (raw) | |
8226 | </p> | |
8227 | </th> | |
8228 | <th> | |
8229 | <p> | |
8230 | tbb | |
8231 | </p> | |
8232 | </th> | |
8233 | <th> | |
8234 | <p> | |
8235 | qthread | |
8236 | </p> | |
8237 | </th> | |
8238 | </tr></thead> | |
8239 | <tbody><tr> | |
8240 | <td> | |
8241 | <p> | |
8242 | 18 µs | |
8243 | </p> | |
8244 | </td> | |
8245 | <td> | |
8246 | <p> | |
8247 | 950 ns | |
8248 | </p> | |
8249 | </td> | |
8250 | <td> | |
8251 | <p> | |
8252 | 900 ns | |
8253 | </p> | |
8254 | </td> | |
8255 | <td> | |
8256 | <p> | |
8257 | 570 ns | |
8258 | </p> | |
8259 | </td> | |
8260 | <td> | |
8261 | <p> | |
8262 | 620 ns | |
8263 | </p> | |
8264 | </td> | |
8265 | </tr></tbody> | |
8266 | </table></div> | |
8267 | </div> | |
8268 | <br class="table-break"><p> | |
8269 | (from <a href="../../../../../performance/fiber/overhead_join.cpp" target="_top">overhead_join.cpp</a>) | |
8270 | </p> | |
8271 | <div class="table"> | |
8272 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance.overhead_of_detach"></a><p class="title"><b>Table 1.2. Overhead of detach</b></p> | |
8273 | <div class="table-contents"><table class="table" summary="Overhead of detach"> | |
8274 | <colgroup> | |
8275 | <col> | |
8276 | <col> | |
8277 | <col> | |
8278 | </colgroup> | |
8279 | <thead><tr> | |
8280 | <th> | |
8281 | <p> | |
8282 | thread | |
8283 | </p> | |
8284 | </th> | |
8285 | <th> | |
8286 | <p> | |
8287 | fiber (atomics) | |
8288 | </p> | |
8289 | </th> | |
8290 | <th> | |
8291 | <p> | |
8292 | fiber (raw) | |
8293 | </p> | |
8294 | </th> | |
8295 | </tr></thead> | |
8296 | <tbody><tr> | |
8297 | <td> | |
8298 | <p> | |
8299 | 126 ns | |
8300 | </p> | |
8301 | </td> | |
8302 | <td> | |
8303 | <p> | |
8304 | 21 ns | |
8305 | </p> | |
8306 | </td> | |
8307 | <td> | |
8308 | <p> | |
8309 | 20 ns | |
8310 | </p> | |
8311 | </td> | |
8312 | </tr></tbody> | |
8313 | </table></div> | |
8314 | </div> | |
8315 | <br class="table-break"><p> | |
8316 | (from <a href="../../../../../performance/fiber/overhead_detach.cpp" target="_top">overhead_detach.cpp</a>) | |
8317 | </p> | |
8318 | <div class="table"> | |
8319 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance.overhead_of_yield"></a><p class="title"><b>Table 1.3. Overhead of yield</b></p> | |
8320 | <div class="table-contents"><table class="table" summary="Overhead of yield"> | |
8321 | <colgroup> | |
8322 | <col> | |
8323 | <col> | |
8324 | <col> | |
8325 | </colgroup> | |
8326 | <thead><tr> | |
8327 | <th> | |
8328 | <p> | |
8329 | thread | |
8330 | </p> | |
8331 | </th> | |
8332 | <th> | |
8333 | <p> | |
8334 | fiber (atomics) | |
8335 | </p> | |
8336 | </th> | |
8337 | <th> | |
8338 | <p> | |
8339 | fiber (raw) | |
8340 | </p> | |
8341 | </th> | |
8342 | </tr></thead> | |
8343 | <tbody><tr> | |
8344 | <td> | |
8345 | <p> | |
8346 | 1.5 µs | |
8347 | </p> | |
8348 | </td> | |
8349 | <td> | |
8350 | <p> | |
8351 | 310 ns | |
8352 | </p> | |
8353 | </td> | |
8354 | <td> | |
8355 | <p> | |
8356 | 330 ns | |
8357 | </p> | |
8358 | </td> | |
8359 | </tr></tbody> | |
8360 | </table></div> | |
8361 | </div> | |
8362 | <br class="table-break"><p> | |
8363 | (from <a href="../../../../../performance/fiber/overhead_yield.cpp" target="_top">overhead_yield.cpp</a>) | |
8364 | </p> | |
8365 | <div class="table"> | |
8366 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance.overhead_of_waiting_on_a_future"></a><p class="title"><b>Table 1.4. Overhead of waiting on a future</b></p> | |
8367 | <div class="table-contents"><table class="table" summary="Overhead of waiting on a future"> | |
8368 | <colgroup> | |
8369 | <col> | |
8370 | <col> | |
8371 | <col> | |
8372 | </colgroup> | |
8373 | <thead><tr> | |
8374 | <th> | |
8375 | <p> | |
8376 | thread | |
8377 | </p> | |
8378 | </th> | |
8379 | <th> | |
8380 | <p> | |
8381 | fiber (atomics) | |
8382 | </p> | |
8383 | </th> | |
8384 | <th> | |
8385 | <p> | |
8386 | fiber (raw) | |
8387 | </p> | |
8388 | </th> | |
8389 | </tr></thead> | |
8390 | <tbody><tr> | |
8391 | <td> | |
8392 | <p> | |
8393 | 16 µs | |
8394 | </p> | |
8395 | </td> | |
8396 | <td> | |
8397 | <p> | |
8398 | 1.40 µs | |
8399 | </p> | |
8400 | </td> | |
8401 | <td> | |
8402 | <p> | |
8403 | 1.38 µs | |
8404 | </p> | |
8405 | </td> | |
8406 | </tr></tbody> | |
8407 | </table></div> | |
8408 | </div> | |
8409 | <br class="table-break"><p> | |
8410 | (from <a href="../../../../../performance/fiber/overhead_future.cpp" target="_top">overhead_future.cpp</a>) | |
8411 | </p> | |
8412 | <div class="table"> | |
8413 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance.overhead_of_fiber_creation__contains_fiber_stack_allocation_and_preparation__fiber_context_construction__scheduler_handling_"></a><p class="title"><b>Table 1.5. Overhead of fiber creation (contains fiber-stack allocation and | |
8414 | preparation, fiber-context construction, scheduler handling)</b></p> | |
8415 | <div class="table-contents"><table class="table" summary="Overhead of fiber creation (contains fiber-stack allocation and | |
8416 | preparation, fiber-context construction, scheduler handling)"> | |
8417 | <colgroup> | |
8418 | <col> | |
8419 | <col> | |
8420 | <col> | |
8421 | </colgroup> | |
8422 | <thead><tr> | |
8423 | <th> | |
8424 | <p> | |
8425 | thread | |
8426 | </p> | |
8427 | </th> | |
8428 | <th> | |
8429 | <p> | |
8430 | fiber (atomics) | |
8431 | </p> | |
8432 | </th> | |
8433 | <th> | |
8434 | <p> | |
8435 | fiber (raw) | |
8436 | </p> | |
8437 | </th> | |
8438 | </tr></thead> | |
8439 | <tbody><tr> | |
8440 | <td> | |
8441 | <p> | |
8442 | 18 µs | |
8443 | </p> | |
8444 | </td> | |
8445 | <td> | |
8446 | <p> | |
8447 | 450 ns | |
8448 | </p> | |
8449 | </td> | |
8450 | <td> | |
8451 | <p> | |
8452 | 445 ns | |
8453 | </p> | |
8454 | </td> | |
8455 | </tr></tbody> | |
8456 | </table></div> | |
8457 | </div> | |
8458 | <br class="table-break"><p> | |
8459 | (from <a href="../../../../../performance/fiber/overhead_create.cpp" target="_top">overhead_create.cpp</a>) | |
8460 | </p> | |
8461 | <div class="table"> | |
8462 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance.scaling_of_creating_and_joining"></a><p class="title"><b>Table 1.6. Scaling of creating and joining</b></p> | |
8463 | <div class="table-contents"><table class="table" summary="Scaling of creating and joining"> | |
8464 | <colgroup> | |
8465 | <col> | |
8466 | <col> | |
8467 | <col> | |
8468 | <col> | |
8469 | </colgroup> | |
8470 | <thead><tr> | |
8471 | <th> | |
8472 | <p> | |
8473 | average of | |
8474 | </p> | |
8475 | </th> | |
8476 | <th> | |
8477 | <p> | |
8478 | thread | |
8479 | </p> | |
8480 | </th> | |
8481 | <th> | |
8482 | <p> | |
8483 | fiber (atomics) | |
8484 | </p> | |
8485 | </th> | |
8486 | <th> | |
8487 | <p> | |
8488 | fiber (raw) | |
8489 | </p> | |
8490 | </th> | |
8491 | </tr></thead> | |
8492 | <tbody> | |
8493 | <tr> | |
8494 | <td> | |
8495 | <p> | |
8496 | 10 | |
8497 | </p> | |
8498 | </td> | |
8499 | <td> | |
8500 | <p> | |
8501 | 8.21 µs | |
8502 | </p> | |
8503 | </td> | |
8504 | <td> | |
8505 | <p> | |
8506 | 1.96 µs | |
8507 | </p> | |
8508 | </td> | |
8509 | <td> | |
8510 | <p> | |
8511 | 1.85 µs | |
8512 | </p> | |
8513 | </td> | |
8514 | </tr> | |
8515 | <tr> | |
8516 | <td> | |
8517 | <p> | |
8518 | 50 | |
8519 | </p> | |
8520 | </td> | |
8521 | <td> | |
8522 | <p> | |
8523 | 6.67 µs | |
8524 | </p> | |
8525 | </td> | |
8526 | <td> | |
8527 | <p> | |
8528 | 1.40 µs | |
8529 | </p> | |
8530 | </td> | |
8531 | <td> | |
8532 | <p> | |
8533 | 1.27 µs | |
8534 | </p> | |
8535 | </td> | |
8536 | </tr> | |
8537 | <tr> | |
8538 | <td> | |
8539 | <p> | |
8540 | 100 | |
8541 | </p> | |
8542 | </td> | |
8543 | <td> | |
8544 | <p> | |
8545 | 6.79 µs | |
8546 | </p> | |
8547 | </td> | |
8548 | <td> | |
8549 | <p> | |
8550 | 1.84 µs | |
8551 | </p> | |
8552 | </td> | |
8553 | <td> | |
8554 | <p> | |
8555 | 1.81 µs | |
8556 | </p> | |
8557 | </td> | |
8558 | </tr> | |
8559 | <tr> | |
8560 | <td> | |
8561 | <p> | |
8562 | 500 | |
8563 | </p> | |
8564 | </td> | |
8565 | <td> | |
8566 | <p> | |
8567 | 8.25 µs | |
8568 | </p> | |
8569 | </td> | |
8570 | <td> | |
8571 | <p> | |
8572 | 1.13 µs | |
8573 | </p> | |
8574 | </td> | |
8575 | <td> | |
8576 | <p> | |
8577 | 1.10 µs | |
8578 | </p> | |
8579 | </td> | |
8580 | </tr> | |
8581 | <tr> | |
8582 | <td> | |
8583 | <p> | |
8584 | 1000 | |
8585 | </p> | |
8586 | </td> | |
8587 | <td> | |
8588 | <p> | |
8589 | 7.71 µs | |
8590 | </p> | |
8591 | </td> | |
8592 | <td> | |
8593 | <p> | |
8594 | 1.46 µs | |
8595 | </p> | |
8596 | </td> | |
8597 | <td> | |
8598 | <p> | |
8599 | 1.26 µs | |
8600 | </p> | |
8601 | </td> | |
8602 | </tr> | |
8603 | <tr> | |
8604 | <td> | |
8605 | <p> | |
8606 | 5000 | |
8607 | </p> | |
8608 | </td> | |
8609 | <td> | |
8610 | <p> | |
8611 | 5.67 µs | |
8612 | </p> | |
8613 | </td> | |
8614 | <td> | |
8615 | <p> | |
8616 | 2.11 µs | |
8617 | </p> | |
8618 | </td> | |
8619 | <td> | |
8620 | <p> | |
8621 | 1.90 µs | |
8622 | </p> | |
8623 | </td> | |
8624 | </tr> | |
8625 | <tr> | |
8626 | <td> | |
8627 | <p> | |
8628 | 10000 | |
8629 | </p> | |
8630 | </td> | |
8631 | <td> | |
8632 | <p> | |
8633 | 5.25 µs | |
8634 | </p> | |
8635 | </td> | |
8636 | <td> | |
8637 | <p> | |
8638 | 2.36 µs | |
8639 | </p> | |
8640 | </td> | |
8641 | <td> | |
8642 | <p> | |
8643 | 1.89 µs | |
8644 | </p> | |
8645 | </td> | |
8646 | </tr> | |
8647 | </tbody> | |
8648 | </table></div> | |
8649 | </div> | |
8650 | <br class="table-break"><p> | |
8651 | (from <a href="../../../../../performance/fiber/scale_join.cpp" target="_top">scale_join.cpp</a>) | |
8652 | </p> | |
8653 | <p> | |
8654 | Numbers of the <a href="https://github.com/atemerev/skynet" target="_top">microbenchmark | |
8655 | <span class="emphasis"><em>syknet</em></span></a> from Alexander Temerev <sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance.f1" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.performance.f1" class="footnote">9</a>]</sup>: | |
8656 | </p> | |
8657 | <div class="table"> | |
8658 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.performance.performance_of_n_100000_actors_goroutines_fibers"></a><p class="title"><b>Table 1.7. performance of N=100000 actors/goroutines/fibers</b></p> | |
8659 | <div class="table-contents"><table class="table" summary="performance of N=100000 actors/goroutines/fibers"> | |
8660 | <colgroup> | |
8661 | <col> | |
8662 | <col> | |
8663 | <col> | |
8664 | <col> | |
8665 | <col> | |
8666 | </colgroup> | |
8667 | <thead><tr> | |
8668 | <th> | |
8669 | <p> | |
8670 | Haskell | stack-1.0.4 | |
8671 | </p> | |
8672 | </th> | |
8673 | <th> | |
8674 | <p> | |
8675 | fiber (single threaded/raw) | gcc-5.2.1 | |
8676 | </p> | |
8677 | </th> | |
8678 | <th> | |
8679 | <p> | |
8680 | fiber (single threaded/atomics) | gcc-5.2.1 | |
8681 | </p> | |
8682 | </th> | |
8683 | <th> | |
8684 | <p> | |
8685 | Erlang | erts-7.0 | |
8686 | </p> | |
8687 | </th> | |
8688 | <th> | |
8689 | <p> | |
8690 | Go | go1.4.2 | |
8691 | </p> | |
8692 | </th> | |
8693 | </tr></thead> | |
8694 | <tbody><tr> | |
8695 | <td> | |
8696 | <p> | |
8697 | 58ms - 108ms | |
8698 | </p> | |
8699 | </td> | |
8700 | <td> | |
8701 | <p> | |
8702 | 205ms - 263ms | |
8703 | </p> | |
8704 | </td> | |
8705 | <td> | |
8706 | <p> | |
8707 | 221ms - 278ms | |
8708 | </p> | |
8709 | </td> | |
8710 | <td> | |
8711 | <p> | |
8712 | 237ms- 470ms | |
8713 | </p> | |
8714 | </td> | |
8715 | <td> | |
8716 | <p> | |
8717 | 614ms - 883ms | |
8718 | </p> | |
8719 | </td> | |
8720 | </tr></tbody> | |
8721 | </table></div> | |
8722 | </div> | |
8723 | <br class="table-break"> | |
8724 | </div> | |
8725 | <div class="section"> | |
8726 | <div class="titlepage"><div><div><h5 class="title"> | |
8727 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom"></a><a name="custom"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom" title="Customization">Customization</a> | |
8728 | </h5></div></div></div> | |
8729 | <h6> | |
8730 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.h0"></a> | |
8731 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.overview"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.overview">Overview</a> | |
8732 | </h6> | |
8733 | <p> | |
8734 | As noted in the <a class="link" href="../../scheduling.html#scheduling">Scheduling</a> section, | |
8735 | by default <span class="bold"><strong>Boost.Fiber</strong></span> uses its own | |
8736 | <a class="link" href="../../scheduling.html#class_round_robin"> <code class="computeroutput">round_robin</code></a> scheduler for each thread. To control the | |
8737 | way <span class="bold"><strong>Boost.Fiber</strong></span> schedules ready fibers | |
8738 | on a particular thread, in general you must follow several steps. This | |
8739 | section discusses those steps, whereas <a class="link" href="../../scheduling.html#scheduling">Scheduling</a> | |
8740 | serves as a reference for the classes involved. | |
8741 | </p> | |
8742 | <p> | |
8743 | The library's fiber manager keeps track of suspended (blocked) fibers. | |
8744 | Only when a fiber becomes ready to run is it passed to the scheduler. | |
8745 | Of course, if there are fewer than two ready fibers, the scheduler's | |
8746 | job is trivial. Only when there are two or more ready fibers does the | |
8747 | particular scheduler implementation start to influence the overall sequence | |
8748 | of fiber execution. | |
8749 | </p> | |
8750 | <p> | |
8751 | In this section we illustrate a simple custom scheduler that honors an | |
8752 | integer fiber priority. We will implement it such that a fiber with higher | |
8753 | priority is preferred over a fiber with lower priority. Any fibers with | |
8754 | equal priority values are serviced on a round-robin basis. | |
8755 | </p> | |
8756 | <p> | |
8757 | The full source code for the examples below is found in <a href="../../../../../examples/priority.cpp" target="_top">priority.cpp</a>. | |
8758 | </p> | |
8759 | <h6> | |
8760 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.h1"></a> | |
8761 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.custom_property_class"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.custom_property_class">Custom | |
8762 | Property Class</a> | |
8763 | </h6> | |
8764 | <p> | |
8765 | The first essential point is that we must associate an integer priority | |
8766 | with each fiber.<sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.f0" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.custom.f0" class="footnote">10</a>]</sup> | |
8767 | </p> | |
8768 | <p> | |
8769 | One might suggest deriving a custom <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> subclass to store | |
8770 | such properties. There are a couple of reasons for the present mechanism. | |
8771 | </p> | |
8772 | <div class="orderedlist"><ol class="orderedlist" type="1"> | |
8773 | <li class="listitem"> | |
8774 | <span class="bold"><strong>Boost.Fiber</strong></span> provides a number of | |
8775 | different ways to launch a fiber. (Consider <a class="link" href="pooled_fixedsize.html#fibers_async"> <code class="computeroutput">fibers::async()</code></a>.) | |
8776 | Higher-level libraries might introduce additional such wrapper functions. | |
8777 | A custom scheduler must associate its custom properties with <span class="emphasis"><em>every</em></span> | |
8778 | fiber in the thread, not only the ones explicitly launched by instantiating | |
8779 | a custom <code class="computeroutput"><span class="identifier">fiber</span></code> subclass. | |
8780 | </li> | |
8781 | <li class="listitem"> | |
8782 | Consider a large existing program that launches fibers in many different | |
8783 | places in the code. We discover a need to introduce a custom scheduler | |
8784 | for a particular thread. If supporting that scheduler's custom properties | |
8785 | required a particular <code class="computeroutput"><span class="identifier">fiber</span></code> | |
8786 | subclass, we would have to hunt down and modify every place that | |
8787 | launches a fiber on that thread. | |
8788 | </li> | |
8789 | <li class="listitem"> | |
8790 | The <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> class is actually just a handle to internal <a class="link" href="../../scheduling.html#class_context"> <code class="computeroutput">context</code></a> data. | |
8791 | A subclass of <code class="computeroutput"><span class="identifier">fiber</span></code> | |
8792 | would not add data to <code class="computeroutput"><span class="identifier">context</span></code>. | |
8793 | </li> | |
8794 | </ol></div> | |
8795 | <p> | |
8796 | The present mechanism allows you to <span class="quote">“<span class="quote">drop in</span>”</span> a custom scheduler | |
8797 | with its attendant custom properties <span class="emphasis"><em>without</em></span> altering | |
8798 | the rest of your application. | |
8799 | </p> | |
8800 | <p> | |
8801 | Instead of deriving a custom scheduler fiber properties subclass from | |
8802 | <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a>, you must instead derive it from <a class="link" href="../../scheduling.html#class_fiber_properties"> <code class="computeroutput">fiber_properties</code></a>. | |
8803 | </p> | |
8804 | <p> | |
8805 | </p> | |
8806 | <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">priority_props</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber_properties</span> <span class="special">{</span> | |
8807 | <span class="keyword">public</span><span class="special">:</span> | |
8808 | <span class="identifier">priority_props</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">*</span> <span class="identifier">ctx</span><span class="special">):</span> | |
8809 | <span class="identifier">fiber_properties</span><span class="special">(</span> <span class="identifier">ctx</span><span class="special">),</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c0" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c1"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> | |
8810 | <span class="identifier">priority_</span><span class="special">(</span> <span class="number">0</span><span class="special">)</span> <span class="special">{</span> | |
8811 | <span class="special">}</span> | |
8812 | ||
8813 | <span class="keyword">int</span> <span class="identifier">get_priority</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> | |
8814 | <span class="keyword">return</span> <span class="identifier">priority_</span><span class="special">;</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c2" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c3"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> | |
8815 | <span class="special">}</span> | |
8816 | ||
8817 | <span class="comment">// Call this method to alter priority, because we must notify</span> | |
8818 | <span class="comment">// priority_scheduler of any change.</span> | |
8819 | <span class="keyword">void</span> <span class="identifier">set_priority</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">p</span><span class="special">)</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c4" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c5"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> | |
8820 | <span class="comment">// Of course, it's only worth reshuffling the queue and all if we're</span> | |
8821 | <span class="comment">// actually changing the priority.</span> | |
8822 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">p</span> <span class="special">!=</span> <span class="identifier">priority_</span><span class="special">)</span> <span class="special">{</span> | |
8823 | <span class="identifier">priority_</span> <span class="special">=</span> <span class="identifier">p</span><span class="special">;</span> | |
8824 | <span class="identifier">notify</span><span class="special">();</span> | |
8825 | <span class="special">}</span> | |
8826 | <span class="special">}</span> | |
8827 | ||
8828 | <span class="comment">// The fiber name of course is solely for purposes of this example</span> | |
8829 | <span class="comment">// program; it has nothing to do with implementing scheduler priority.</span> | |
8830 | <span class="comment">// This is a public data member -- not requiring set/get access methods --</span> | |
8831 | <span class="comment">// because we need not inform the scheduler of any change.</span> | |
8832 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">name</span><span class="special">;</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c6" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c7"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a> | |
8833 | <span class="keyword">private</span><span class="special">:</span> | |
8834 | <span class="keyword">int</span> <span class="identifier">priority_</span><span class="special">;</span> | |
8835 | <span class="special">};</span> | |
8836 | </pre> | |
8837 | <p> | |
8838 | </p> | |
8839 | <div class="calloutlist"><table border="0" summary="Callout list"> | |
8840 | <tr> | |
8841 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c1"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c0"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> </p></td> | |
8842 | <td valign="top" align="left"><p> | |
8843 | Your subclass constructor must accept a <code class="literal"> <a class="link" href="../../scheduling.html#class_context"> <code class="computeroutput">context</code></a>*</code> | |
8844 | and pass it to the <code class="computeroutput"><span class="identifier">fiber_properties</span></code> | |
8845 | constructor. | |
8846 | </p></td> | |
8847 | </tr> | |
8848 | <tr> | |
8849 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c3"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c2"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> </p></td> | |
8850 | <td valign="top" align="left"><p> | |
8851 | Provide read access methods at your own discretion. | |
8852 | </p></td> | |
8853 | </tr> | |
8854 | <tr> | |
8855 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c5"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c4"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> </p></td> | |
8856 | <td valign="top" align="left"><p> | |
8857 | It's important to call <code class="computeroutput"><span class="identifier">notify</span><span class="special">()</span></code> on any change in a property that | |
8858 | can affect the scheduler's behavior. Therefore, such modifications | |
8859 | should only be performed through an access method. | |
8860 | </p></td> | |
8861 | </tr> | |
8862 | <tr> | |
8863 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c7"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c6"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a> </p></td> | |
8864 | <td valign="top" align="left"><p> | |
8865 | A property that does not affect the scheduler does not need access | |
8866 | methods. | |
8867 | </p></td> | |
8868 | </tr> | |
8869 | </table></div> | |
8870 | <h6> | |
8871 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.h2"></a> | |
8872 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.custom_scheduler_class"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.custom_scheduler_class">Custom | |
8873 | Scheduler Class</a> | |
8874 | </h6> | |
8875 | <p> | |
8876 | Now we can derive a custom scheduler from <a class="link" href="../../scheduling.html#class_sched_algorithm_with_properties"> <code class="computeroutput">sched_algorithm_with_properties<></code></a>, | |
8877 | specifying our custom property class <code class="computeroutput"><span class="identifier">priority_props</span></code> | |
8878 | as the template parameter. | |
8879 | </p> | |
8880 | <p> | |
8881 | </p> | |
8882 | <pre class="programlisting"><span class="keyword">class</span> <span class="identifier">priority_scheduler</span> <span class="special">:</span> | |
8883 | <span class="keyword">public</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">sched_algorithm_with_properties</span><span class="special"><</span> <span class="identifier">priority_props</span> <span class="special">></span> <span class="special">{</span> | |
8884 | <span class="keyword">private</span><span class="special">:</span> | |
8885 | <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">scheduler</span><span class="special">::</span><span class="identifier">ready_queue_t</span><a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c8" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c9"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> <span class="identifier">rqueue_t</span><span class="special">;</span> | |
8886 | ||
8887 | <span class="identifier">rqueue_t</span> <span class="identifier">rqueue_</span><span class="special">;</span> | |
8888 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">mutex</span> <span class="identifier">mtx_</span><span class="special">{};</span> | |
8889 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">condition_variable</span> <span class="identifier">cnd_</span><span class="special">{};</span> | |
8890 | <span class="keyword">bool</span> <span class="identifier">flag_</span><span class="special">{</span> <span class="keyword">false</span> <span class="special">};</span> | |
8891 | ||
8892 | <span class="keyword">public</span><span class="special">:</span> | |
8893 | <span class="identifier">priority_scheduler</span><span class="special">()</span> <span class="special">:</span> | |
8894 | <span class="identifier">rqueue_</span><span class="special">()</span> <span class="special">{</span> | |
8895 | <span class="special">}</span> | |
8896 | ||
8897 | <span class="comment">// For a subclass of sched_algorithm_with_properties<>, it's important to</span> | |
8898 | <span class="comment">// override the correct awakened() overload.</span> | |
8899 | <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c10" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c11"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">awakened</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">*</span> <span class="identifier">ctx</span><span class="special">,</span> <span class="identifier">priority_props</span> <span class="special">&</span> <span class="identifier">props</span><span class="special">)</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
8900 | <span class="keyword">int</span> <span class="identifier">ctx_priority</span> <span class="special">=</span> <span class="identifier">props</span><span class="special">.</span><span class="identifier">get_priority</span><span class="special">();</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c12" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c13"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> | |
8901 | <span class="comment">// With this scheduler, fibers with higher priority values are</span> | |
8902 | <span class="comment">// preferred over fibers with lower priority values. But fibers with</span> | |
8903 | <span class="comment">// equal priority values are processed in round-robin fashion. So when</span> | |
8904 | <span class="comment">// we're handed a new context*, put it at the end of the fibers</span> | |
8905 | <span class="comment">// with that same priority. In other words: search for the first fiber</span> | |
8906 | <span class="comment">// in the queue with LOWER priority, and insert before that one.</span> | |
8907 | <span class="identifier">rqueue_t</span><span class="special">::</span><span class="identifier">iterator</span> <span class="identifier">i</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">find_if</span><span class="special">(</span> <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> | |
8908 | <span class="special">[</span><span class="identifier">ctx_priority</span><span class="special">,</span><span class="keyword">this</span><span class="special">](</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">&</span> <span class="identifier">c</span><span class="special">)</span> | |
8909 | <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">properties</span><span class="special">(</span> <span class="special">&</span><span class="identifier">c</span> <span class="special">).</span><span class="identifier">get_priority</span><span class="special">()</span> <span class="special"><</span> <span class="identifier">ctx_priority</span><span class="special">;</span> <span class="special">}));</span> | |
8910 | <span class="comment">// Now, whether or not we found a fiber with lower priority,</span> | |
8911 | <span class="comment">// insert this new fiber here.</span> | |
8912 | <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">insert</span><span class="special">(</span> <span class="identifier">i</span><span class="special">,</span> <span class="special">*</span> <span class="identifier">ctx</span><span class="special">);</span> | |
8913 | <span class="special">}</span> | |
8914 | ||
8915 | <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c14" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c15"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a><span class="keyword">virtual</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">*</span> <span class="identifier">pick_next</span><span class="special">()</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
8916 | <span class="comment">// if ready queue is empty, just tell caller</span> | |
8917 | <span class="keyword">if</span> <span class="special">(</span> <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">empty</span><span class="special">()</span> <span class="special">)</span> <span class="special">{</span> | |
8918 | <span class="keyword">return</span> <span class="keyword">nullptr</span><span class="special">;</span> | |
8919 | <span class="special">}</span> | |
8920 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">*</span> <span class="identifier">ctx</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">front</span><span class="special">()</span> <span class="special">);</span> | |
8921 | <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">pop_front</span><span class="special">();</span> | |
8922 | <span class="keyword">return</span> <span class="identifier">ctx</span><span class="special">;</span> | |
8923 | <span class="special">}</span> | |
8924 | ||
8925 | <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c16" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c17"><img src="../../../../../../../doc/src/images/callouts/5.png" alt="5" border="0"></a><span class="keyword">virtual</span> <span class="keyword">bool</span> <span class="identifier">has_ready_fibers</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
8926 | <span class="keyword">return</span> <span class="special">!</span> <span class="identifier">rqueue_</span><span class="special">.</span><span class="identifier">empty</span><span class="special">();</span> | |
8927 | <span class="special">}</span> | |
8928 | ||
8929 | <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c18" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c19"><img src="../../../../../../../doc/src/images/callouts/6.png" alt="6" border="0"></a><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">property_change</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">context</span> <span class="special">*</span> <span class="identifier">ctx</span><span class="special">,</span> <span class="identifier">priority_props</span> <span class="special">&</span> <span class="identifier">props</span><span class="special">)</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
8930 | <span class="comment">// Although our priority_props class defines multiple properties, only</span> | |
8931 | <span class="comment">// one of them (priority) actually calls notify() when changed. The</span> | |
8932 | <span class="comment">// point of a property_change() override is to reshuffle the ready</span> | |
8933 | <span class="comment">// queue according to the updated priority value.</span> | |
8934 | ||
8935 | <span class="comment">// 'ctx' might not be in our queue at all, if caller is changing the</span> | |
8936 | <span class="comment">// priority of (say) the running fiber. If it's not there, no need to</span> | |
8937 | <span class="comment">// move it: we'll handle it next time it hits awakened().</span> | |
8938 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">ctx</span><span class="special">-></span><span class="identifier">ready_is_linked</span><span class="special">())</span> <span class="special">{</span> <a class="co" name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c20" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c21"><img src="../../../../../../../doc/src/images/callouts/7.png" alt="7" border="0"></a> | |
8939 | <span class="keyword">return</span><span class="special">;</span> | |
8940 | <span class="special">}</span> | |
8941 | ||
8942 | <span class="comment">// Found ctx: unlink it</span> | |
8943 | <span class="identifier">ctx</span><span class="special">-></span><span class="identifier">ready_unlink</span><span class="special">();</span> | |
8944 | ||
8945 | <span class="comment">// Here we know that ctx was in our ready queue, but we've unlinked</span> | |
8946 | <span class="comment">// it. We happen to have a method that will (re-)add a context* to the</span> | |
8947 | <span class="comment">// right place in the ready queue.</span> | |
8948 | <span class="identifier">awakened</span><span class="special">(</span> <span class="identifier">ctx</span><span class="special">,</span> <span class="identifier">props</span><span class="special">);</span> | |
8949 | <span class="special">}</span> | |
8950 | ||
8951 | <span class="keyword">void</span> <span class="identifier">suspend_until</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">steady_clock</span><span class="special">::</span><span class="identifier">time_point</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">time_point</span><span class="special">)</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
8952 | <span class="keyword">if</span> <span class="special">(</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">chrono</span><span class="special">::</span><span class="identifier">steady_clock</span><span class="special">::</span><span class="identifier">time_point</span><span class="special">::</span><span class="identifier">max</span><span class="special">)()</span> <span class="special">==</span> <span class="identifier">time_point</span><span class="special">)</span> <span class="special">{</span> | |
8953 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">></span> <span class="identifier">lk</span><span class="special">(</span> <span class="identifier">mtx_</span><span class="special">);</span> | |
8954 | <span class="identifier">cnd_</span><span class="special">.</span><span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">,</span> <span class="special">[</span><span class="keyword">this</span><span class="special">](){</span> <span class="keyword">return</span> <span class="identifier">flag_</span><span class="special">;</span> <span class="special">});</span> | |
8955 | <span class="identifier">flag_</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span> | |
8956 | <span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span> | |
8957 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">></span> <span class="identifier">lk</span><span class="special">(</span> <span class="identifier">mtx_</span><span class="special">);</span> | |
8958 | <span class="identifier">cnd_</span><span class="special">.</span><span class="identifier">wait_until</span><span class="special">(</span> <span class="identifier">lk</span><span class="special">,</span> <span class="identifier">time_point</span><span class="special">,</span> <span class="special">[</span><span class="keyword">this</span><span class="special">](){</span> <span class="keyword">return</span> <span class="identifier">flag_</span><span class="special">;</span> <span class="special">});</span> | |
8959 | <span class="identifier">flag_</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span> | |
8960 | <span class="special">}</span> | |
8961 | <span class="special">}</span> | |
8962 | ||
8963 | <span class="keyword">void</span> <span class="identifier">notify</span><span class="special">()</span> <span class="keyword">noexcept</span> <span class="special">{</span> | |
8964 | <span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_lock</span><span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">mutex</span> <span class="special">></span> <span class="identifier">lk</span><span class="special">(</span> <span class="identifier">mtx_</span><span class="special">);</span> | |
8965 | <span class="identifier">flag_</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span> | |
8966 | <span class="identifier">lk</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span> | |
8967 | <span class="identifier">cnd_</span><span class="special">.</span><span class="identifier">notify_all</span><span class="special">();</span> | |
8968 | <span class="special">}</span> | |
8969 | <span class="special">};</span> | |
8970 | </pre> | |
8971 | <p> | |
8972 | </p> | |
8973 | <div class="calloutlist"><table border="0" summary="Callout list"> | |
8974 | <tr> | |
8975 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c9"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c8"><img src="../../../../../../../doc/src/images/callouts/1.png" alt="1" border="0"></a> </p></td> | |
8976 | <td valign="top" align="left"><p> | |
8977 | See <a class="link" href="../../scheduling.html#ready_queue_t">ready_queue_t</a>. | |
8978 | </p></td> | |
8979 | </tr> | |
8980 | <tr> | |
8981 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c11"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c10"><img src="../../../../../../../doc/src/images/callouts/2.png" alt="2" border="0"></a> </p></td> | |
8982 | <td valign="top" align="left"><p> | |
8983 | You must override the <a class="link" href="../../scheduling.html#sched_algorithm_with_properties_awakened"> <code class="computeroutput">sched_algorithm_with_properties::awakened()</code></a> | |
8984 | method. | |
8985 | This is how your scheduler receives notification of a fiber that | |
8986 | has become ready to run. | |
8987 | </p></td> | |
8988 | </tr> | |
8989 | <tr> | |
8990 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c13"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c12"><img src="../../../../../../../doc/src/images/callouts/3.png" alt="3" border="0"></a> </p></td> | |
8991 | <td valign="top" align="left"><p> | |
8992 | <code class="computeroutput"><span class="identifier">props</span></code> is the instance | |
8993 | of priority_props associated with the passed fiber <code class="computeroutput"><span class="identifier">ctx</span></code>. | |
8994 | </p></td> | |
8995 | </tr> | |
8996 | <tr> | |
8997 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c15"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c14"><img src="../../../../../../../doc/src/images/callouts/4.png" alt="4" border="0"></a> </p></td> | |
8998 | <td valign="top" align="left"><p> | |
8999 | You must override the <a class="link" href="../../scheduling.html#sched_algorithm_with_properties_pick_next"> <code class="computeroutput">sched_algorithm_with_properties::pick_next()</code></a> | |
9000 | method. | |
9001 | This is how your scheduler actually advises the fiber manager of | |
9002 | the next fiber to run. | |
9003 | </p></td> | |
9004 | </tr> | |
9005 | <tr> | |
9006 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c17"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c16"><img src="../../../../../../../doc/src/images/callouts/5.png" alt="5" border="0"></a> </p></td> | |
9007 | <td valign="top" align="left"><p> | |
9008 | You must override <a class="link" href="../../scheduling.html#sched_algorithm_with_properties_has_ready_fibers"> <code class="computeroutput">sched_algorithm_with_properties::has_ready_fibers()</code></a> | |
9009 | to | |
9010 | inform the fiber manager of the state of your ready queue. | |
9011 | </p></td> | |
9012 | </tr> | |
9013 | <tr> | |
9014 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c19"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c18"><img src="../../../../../../../doc/src/images/callouts/6.png" alt="6" border="0"></a> </p></td> | |
9015 | <td valign="top" align="left"><p> | |
9016 | Overriding <a class="link" href="../../scheduling.html#sched_algorithm_with_properties_property_change"> <code class="computeroutput">sched_algorithm_with_properties::property_change()</code></a> | |
9017 | is | |
9018 | optional. This override handles the case in which the running fiber | |
9019 | changes the priority of another ready fiber: a fiber already in our | |
9020 | queue. In that case, move the updated fiber within the queue. | |
9021 | </p></td> | |
9022 | </tr> | |
9023 | <tr> | |
9024 | <td width="5%" valign="top" align="left"><p><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c21"></a><a href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.c20"><img src="../../../../../../../doc/src/images/callouts/7.png" alt="7" border="0"></a> </p></td> | |
9025 | <td valign="top" align="left"><p> | |
9026 | Your <code class="computeroutput"><span class="identifier">property_change</span><span class="special">()</span></code> override must be able to handle | |
9027 | the case in which the passed <code class="computeroutput"><span class="identifier">ctx</span></code> | |
9028 | is not in your ready queue. It might be running, or it might be blocked. | |
9029 | </p></td> | |
9030 | </tr> | |
9031 | </table></div> | |
9032 | <p> | |
9033 | Our example <code class="computeroutput"><span class="identifier">priority_scheduler</span></code> | |
9034 | doesn't override <a class="link" href="../../scheduling.html#sched_algorithm_with_properties_new_properties"> <code class="computeroutput">sched_algorithm_with_properties::new_properties()</code></a>: | |
9035 | we're content with allocating <code class="computeroutput"><span class="identifier">priority_props</span></code> | |
9036 | instances on the heap. | |
9037 | </p> | |
9038 | <h6> | |
9039 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.h3"></a> | |
9040 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.replace_default_scheduler"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.replace_default_scheduler">Replace | |
9041 | Default Scheduler</a> | |
9042 | </h6> | |
9043 | <p> | |
9044 | You must call <a class="link" href="../../fiber_mgmt/fiber.html#use_scheduling_algorithm"> <code class="computeroutput">use_scheduling_algorithm()</code></a> at the | |
9045 | start of each thread on which you want <span class="bold"><strong>Boost.Fiber</strong></span> | |
9046 | to use your custom scheduler rather than its own default <a class="link" href="../../scheduling.html#class_round_robin"> <code class="computeroutput">round_robin</code></a>. | |
9047 | Specifically, you must call <code class="computeroutput"><span class="identifier">use_scheduling_algorithm</span><span class="special">()</span></code> before performing any other <span class="bold"><strong>Boost.Fiber</strong></span> operations on that thread. | |
9048 | </p> | |
9049 | <p> | |
9050 | </p> | |
9051 | <pre class="programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">argc</span><span class="special">,</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">argv</span><span class="special">[])</span> <span class="special">{</span> | |
9052 | <span class="comment">// make sure we use our priority_scheduler rather than default round_robin</span> | |
9053 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">use_scheduling_algorithm</span><span class="special"><</span> <span class="identifier">priority_scheduler</span> <span class="special">>();</span> | |
9054 | <span class="special">...</span> | |
9055 | <span class="special">}</span> | |
9056 | </pre> | |
9057 | <p> | |
9058 | </p> | |
9059 | <h6> | |
9060 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.h4"></a> | |
9061 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.custom.use_properties"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.use_properties">Use | |
9062 | Properties</a> | |
9063 | </h6> | |
9064 | <p> | |
9065 | The running fiber can access its own <a class="link" href="../../scheduling.html#class_fiber_properties"> <code class="computeroutput">fiber_properties</code></a> subclass | |
9066 | instance by calling <a class="link" href="../../fiber_mgmt/this_fiber.html#this_fiber_properties"> <code class="computeroutput">this_fiber::properties()</code></a>. Although | |
9067 | <code class="computeroutput"><span class="identifier">properties</span><span class="special"><>()</span></code> | |
9068 | is a nullary function, you must pass, as a template parameter, the <code class="computeroutput"><span class="identifier">fiber_properties</span></code> subclass. | |
9069 | </p> | |
9070 | <p> | |
9071 | </p> | |
9072 | <pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">properties</span><span class="special"><</span> <span class="identifier">priority_props</span> <span class="special">>().</span><span class="identifier">name</span> <span class="special">=</span> <span class="string">"main"</span><span class="special">;</span> | |
9073 | </pre> | |
9074 | <p> | |
9075 | </p> | |
9076 | <p> | |
9077 | Given a <a class="link" href="../../fiber_mgmt/fiber.html#class_fiber"> <code class="computeroutput">fiber</code></a> instance still connected with a running fiber | |
9078 | (that is, not <a class="link" href="../../fiber_mgmt/fiber.html#fiber_detach"> <code class="computeroutput">fiber::detach()</code></a>ed), you may access that fiber's | |
9079 | properties using <a class="link" href="../../fiber_mgmt/fiber.html#fiber_properties"> <code class="computeroutput">fiber::properties()</code></a>. As with <code class="computeroutput"><span class="identifier">this_fiber</span><span class="special">::</span><span class="identifier">properties</span><span class="special"><>()</span></code>, | |
9080 | you must pass your <code class="computeroutput"><span class="identifier">fiber_properties</span></code> | |
9081 | subclass as the template parameter. | |
9082 | </p> | |
9083 | <p> | |
9084 | </p> | |
9085 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Fn</span> <span class="special">></span> | |
9086 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span> <span class="identifier">launch</span><span class="special">(</span> <span class="identifier">Fn</span> <span class="special">&&</span> <span class="identifier">func</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">name</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">priority</span><span class="special">)</span> <span class="special">{</span> | |
9087 | <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">fiber</span> <span class="identifier">fiber</span><span class="special">(</span> <span class="identifier">func</span><span class="special">);</span> | |
9088 | <span class="identifier">priority_props</span> <span class="special">&</span> <span class="identifier">props</span><span class="special">(</span> <span class="identifier">fiber</span><span class="special">.</span><span class="identifier">properties</span><span class="special"><</span> <span class="identifier">priority_props</span> <span class="special">>()</span> <span class="special">);</span> | |
9089 | <span class="identifier">props</span><span class="special">.</span><span class="identifier">name</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">;</span> | |
9090 | <span class="identifier">props</span><span class="special">.</span><span class="identifier">set_priority</span><span class="special">(</span> <span class="identifier">priority</span><span class="special">);</span> | |
9091 | <span class="keyword">return</span> <span class="identifier">fiber</span><span class="special">;</span> | |
9092 | <span class="special">}</span> | |
9093 | </pre> | |
9094 | <p> | |
9095 | </p> | |
9096 | <p> | |
9097 | Launching a new fiber schedules that fiber as ready, but does <span class="emphasis"><em>not</em></span> | |
9098 | immediately enter its <span class="emphasis"><em>fiber-function</em></span>. The current | |
9099 | fiber retains control until it blocks (or yields, or terminates) for | |
9100 | some other reason. As shown in the <code class="computeroutput"><span class="identifier">launch</span><span class="special">()</span></code> function above, it is reasonable to | |
9101 | launch a fiber and immediately set relevant properties -- such as, for | |
9102 | instance, its priority. Your custom scheduler can then make use of this | |
9103 | information next time the fiber manager calls <a class="link" href="../../scheduling.html#sched_algorithm_with_properties_pick_next"> <code class="computeroutput">sched_algorithm_with_properties::pick_next()</code></a>. | |
9104 | </p> | |
9105 | </div> | |
9106 | <div class="section"> | |
9107 | <div class="titlepage"><div><div><h5 class="title"> | |
9108 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale" title="Rationale">Rationale</a> | |
9109 | </h5></div></div></div> | |
9110 | <h6> | |
9111 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.h0"></a> | |
9112 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.distinction_between_coroutines_and_fibers"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.distinction_between_coroutines_and_fibers">distinction | |
9113 | between coroutines and fibers</a> | |
9114 | </h6> | |
9115 | <p> | |
9116 | The fiber library extends the coroutine library by adding a scheduler | |
9117 | and synchronization mechanisms. | |
9118 | </p> | |
9119 | <div class="itemizedlist"><ul class="itemizedlist" type="disc"> | |
9120 | <li class="listitem"> | |
9121 | a coroutine yields | |
9122 | </li> | |
9123 | <li class="listitem"> | |
9124 | a fiber blocks | |
9125 | </li> | |
9126 | </ul></div> | |
9127 | <p> | |
9128 | When a coroutine yields, it passes control directly to its caller (or, | |
9129 | in the case of symmetric coroutines, a designated other coroutine). When | |
9130 | a fiber blocks, it implicitly passes control to the fiber scheduler. | |
9131 | Coroutines have no scheduler because they need no scheduler.<sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.f0" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.f0" class="footnote">11</a>]</sup>. | |
9132 | </p> | |
9133 | <h6> | |
9134 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.h1"></a> | |
9135 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.what_about_transactional_memory"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.what_about_transactional_memory">what | |
9136 | about transactional memory</a> | |
9137 | </h6> | |
9138 | <p> | |
9139 | GCC supports transactional memory since version 4.7. Unfortunately tests | |
9140 | show that transactional memory is slower (ca. 4x) than spinlocks using | |
9141 | atomics. Once transactional memory is improved (supporting hybrid tm), | |
9142 | spinlocks will be replaced by __transaction_atomic{} statements surrounding | |
9143 | the critical sections. | |
9144 | </p> | |
9145 | <h6> | |
9146 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.h2"></a> | |
9147 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.synchronization_between_fibers_running_in_different_threads"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.synchronization_between_fibers_running_in_different_threads">synchronization | |
9148 | between fibers running in different threads</a> | |
9149 | </h6> | |
9150 | <p> | |
9151 | Synchronization classes from <a href="http://www.boost.org/doc/libs/release/libs/thread/index.html" target="_top">Boost.Thread</a> | |
9152 | block the entire thread. In contrast, the synchronization classes from | |
9153 | <span class="bold"><strong>Boost.Fiber</strong></span> block only specific fibers, | |
9154 | so that the scheduler can still keep the thread busy running other fibers | |
9155 | in the meantime. The synchronization classes from <span class="bold"><strong>Boost.Fiber</strong></span> | |
9156 | are designed to be thread-safe, i.e. it is possible to synchronize fibers | |
9157 | running in different threads as well as fibers running in the same thread. | |
9158 | (However, there is a build option to disable cross-thread fiber synchronization | |
9159 | support; see <a class="link" href="../../overview.html#cross_thread_sync">this description</a>.) | |
9160 | </p> | |
9161 | <a name="spurious_wakeup"></a><h6> | |
9162 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.h3"></a> | |
9163 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.spurious_wakeup"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.spurious_wakeup">spurious | |
9164 | wakeup</a> | |
9165 | </h6> | |
9166 | <p> | |
9167 | Spurious wakeup can happen when using <a href="http://en.cppreference.com/w/cpp/thread/condition_variable" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">condition_variable</span></code></a>: the condition | |
9168 | variable appears to be have been signaled while the awaited condition | |
9169 | may still be false. Spurious wakeup can happen repeatedly and is caused | |
9170 | on some multiprocessor systems where making <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">condition_variable</span></code> | |
9171 | wakeup completely predictable would slow down all <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">condition_variable</span></code> | |
9172 | operations.<sup>[<a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.f1" href="#ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.f1" class="footnote">12</a>]</sup> | |
9173 | </p> | |
9174 | <p> | |
9175 | <a class="link" href="pooled_fixedsize.html#class_condition_variable"> <code class="computeroutput">condition_variable</code></a> is not subject to spurious | |
9176 | wakeup. Nonetheless it is prudent to test the business-logic condition | |
9177 | in a <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> | |
9178 | loop — or, equivalently, use one of the <code class="computeroutput"><span class="identifier">wait</span><span class="special">(</span> <span class="identifier">lock</span><span class="special">,</span> <span class="identifier">predicate</span> | |
9179 | <span class="special">)</span></code> overloads. | |
9180 | </p> | |
9181 | <p> | |
9182 | See also <a class="link" href="pooled_fixedsize.html#condition_variable_spurious_wakeups">No Spurious | |
9183 | Wakeups</a>. | |
9184 | </p> | |
9185 | <h6> | |
9186 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.h4"></a> | |
9187 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.migrating_fibers_between_threads"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.migrating_fibers_between_threads">migrating | |
9188 | fibers between threads</a> | |
9189 | </h6> | |
9190 | <p> | |
9191 | Support for migrating fibers between threads has been integrated. The | |
9192 | user-defined scheduler must call <a class="link" href="../../scheduling.html#context_migrate"> <code class="computeroutput">context::migrate()</code></a> on | |
9193 | a fiber-context on the destination thread, passing <code class="computeroutput"><span class="identifier">migrate</span><span class="special">()</span></code> the fiber-context to migrate. (For | |
9194 | more information about custom schedulers, see <a class="link" href="pooled_fixedsize.html#custom">Customization</a>.) | |
9195 | Examples <code class="computeroutput"><span class="identifier">work_sharing</span></code> | |
9196 | and <code class="computeroutput"><span class="identifier">work_stealing</span></code> in | |
9197 | directory <code class="computeroutput"><span class="identifier">examples</span></code> might | |
9198 | be used as a blueprint. | |
9199 | </p> | |
9200 | <p> | |
9201 | See also <a class="link" href="pooled_fixedsize.html#migration">Migrating fibers between threads</a>. | |
9202 | </p> | |
9203 | <h6> | |
9204 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.h5"></a> | |
9205 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.support_for_boost_asio"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.support_for_boost_asio">support | |
9206 | for Boost.Asio</a> | |
9207 | </h6> | |
9208 | <p> | |
9209 | Support for <a href="http://www.boost.org/doc/libs/release/libs/asio/index.html" target="_top">Boost.Asio</a>'s | |
9210 | <span class="emphasis"><em>async-result</em></span> is not part of the official API. However, | |
9211 | to integrate with a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_service</span></code>, | |
9212 | see <a class="link" href="pooled_fixedsize.html#integration">Sharing a Thread with Another Main Loop</a>. | |
9213 | To interface smoothly with an arbitrary Asio async I/O operation, see | |
9214 | <a class="link" href="pooled_fixedsize.html#callbacks_asio">Then There's <a href="http://www.boost.org/doc/libs/release/libs/asio/index.html" target="_top">Boost.Asio</a></a>. | |
9215 | </p> | |
9216 | <h6> | |
9217 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.h6"></a> | |
9218 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.tested_compilers"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.tested_compilers">tested | |
9219 | compilers</a> | |
9220 | </h6> | |
9221 | <p> | |
9222 | The library was tested with GCC-5.1.1, Clang-3.6.0 and MSVC-14.0 in c++11-mode. | |
9223 | </p> | |
9224 | <h6> | |
9225 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.h7"></a> | |
9226 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.supported_architectures"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.supported_architectures">supported | |
9227 | architectures</a> | |
9228 | </h6> | |
9229 | <p> | |
9230 | <span class="bold"><strong>Boost.Fiber</strong></span> depends on <a href="http://www.boost.org/doc/libs/release/libs/context/index.html" target="_top">Boost.Context</a> | |
9231 | - the list of supported architectures can be found <a href="http://www.boost.org/doc/libs/release/libs/context/doc/html/context/architectures.html" target="_top">here</a>. | |
9232 | </p> | |
9233 | </div> | |
9234 | <div class="section"> | |
9235 | <div class="titlepage"><div><div><h5 class="title"> | |
9236 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.acknowledgements"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.acknowledgements" title="Acknowledgments">Acknowledgments</a> | |
9237 | </h5></div></div></div> | |
9238 | <p> | |
9239 | I'd like to thank Agustín Bergé, Eugene Yakubovich, Giovanni Piero | |
9240 | Deretta and especially Nat Goodspeed. | |
9241 | </p> | |
9242 | </div> | |
9243 | <div class="section"> | |
9244 | <div class="titlepage"><div><div><h5 class="title"> | |
9245 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.installing"></a><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.installing" title="Appendix: Installing and Running Tests">Appendix: | |
9246 | Installing and Running Tests</a> | |
9247 | </h5></div></div></div> | |
9248 | <h6> | |
9249 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.installing.h0"></a> | |
9250 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.installing.installing_the_fiber_library"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.installing.installing_the_fiber_library">Installing | |
9251 | the Fiber library</a> | |
9252 | </h6> | |
9253 | <p> | |
9254 | As Fiber is not yet officially part of Boost, it is necessary to embed | |
9255 | it in an existing <a href="http://www.boost.org/users/download/" target="_top">Boost | |
9256 | source tree</a>. | |
9257 | </p> | |
9258 | <p> | |
9259 | The <a href="https://github.com/olk/boost-fiber/archive/master.zip" target="_top">downloaded | |
9260 | Fiber library</a> can be placed into an existing Boost source tree | |
9261 | by moving the top-level Fiber directory to <code class="computeroutput"><span class="identifier">libs</span><span class="special">/</span><span class="identifier">fiber</span></code> | |
9262 | under the top-level Boost directory, then further moving <code class="computeroutput"><span class="identifier">libs</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">include</span><span class="special">/</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span></code> (in other words, the Fiber library's | |
9263 | <code class="computeroutput"><span class="identifier">include</span><span class="special">/</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span></code> directory) to <code class="computeroutput"><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span></code> | |
9264 | under the top-level Boost directory. | |
9265 | </p> | |
9266 | <p> | |
9267 | On a Posix system such as Linux or OS X, you may use symlinks instead. | |
9268 | </p> | |
9269 | <p> | |
9270 | Create a symlink from the Boost directory's <code class="computeroutput"><span class="identifier">libs</span><span class="special">/</span><span class="identifier">fiber</span></code> | |
9271 | to the top-level Fiber directory, e.g.: | |
9272 | </p> | |
9273 | <pre class="programlisting"><span class="identifier">cd</span> <span class="special">~/</span><span class="identifier">boost_1_61_0</span> | |
9274 | <span class="identifier">ln</span> <span class="special">-</span><span class="identifier">s</span> <span class="special">~/</span><span class="identifier">boost</span><span class="special">-</span><span class="identifier">fiber</span><span class="special">-</span><span class="identifier">master</span> <span class="identifier">libs</span><span class="special">/</span><span class="identifier">fiber</span> | |
9275 | </pre> | |
9276 | <p> | |
9277 | Then create a symlink from the Boost directory's <code class="computeroutput"><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span></code> | |
9278 | to the Fiber library's <code class="computeroutput"><span class="identifier">include</span><span class="special">/</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span></code> | |
9279 | directory: | |
9280 | </p> | |
9281 | <pre class="programlisting"><span class="identifier">cd</span> <span class="identifier">boost</span> | |
9282 | <span class="identifier">ln</span> <span class="special">-</span><span class="identifier">s</span> <span class="special">../</span><span class="identifier">libs</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">include</span><span class="special">/</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span> <span class="identifier">fiber</span> | |
9283 | </pre> | |
9284 | <p> | |
9285 | For some versions of the Boost.Build system, it was important to use | |
9286 | a relative symlink of that form for <code class="computeroutput"><span class="identifier">boost</span><span class="special">/</span><span class="identifier">fiber</span></code>. | |
9287 | </p> | |
9288 | <a name="tests"></a><h6> | |
9289 | <a name="fiber.stack.protected_fixedsize.pooled_fixedsize.installing.h1"></a> | |
9290 | <span><a name="fiber.stack.protected_fixedsize.pooled_fixedsize.installing.running_tests"></a></span><a class="link" href="pooled_fixedsize.html#fiber.stack.protected_fixedsize.pooled_fixedsize.installing.running_tests">Running | |
9291 | Tests</a> | |
9292 | </h6> | |
9293 | <p> | |
9294 | Once the Fiber library has been overlaid (or symlinked) into the Boost | |
9295 | source tree this way, the Boost.Build system can build it like any other | |
9296 | Boost library. In particular: | |
9297 | </p> | |
9298 | <pre class="programlisting"><span class="identifier">cd</span> <span class="special">~/</span><span class="identifier">boost_1_61_0</span> | |
9299 | <span class="special">./</span><span class="identifier">bootstrap</span><span class="special">.</span><span class="identifier">sh</span> | |
9300 | <span class="special">./</span><span class="identifier">b2</span> <span class="identifier">libs</span><span class="special">/</span><span class="identifier">fiber</span><span class="special">/</span><span class="identifier">test</span> | |
9301 | </pre> | |
9302 | <p> | |
9303 | On Windows, the commands would look more like: | |
9304 | </p> | |
9305 | <pre class="programlisting"><span class="identifier">cd</span> <span class="special">/</span><span class="identifier">D</span> <span class="special">%</span><span class="identifier">HOMEDRIVE</span><span class="special">%%</span><span class="identifier">HOMEPATH</span><span class="special">%\</span><span class="identifier">boost_1_61_0</span> | |
9306 | <span class="identifier">bootstrap</span> | |
9307 | <span class="identifier">b2</span> <span class="identifier">libs</span><span class="special">\</span><span class="identifier">fiber</span><span class="special">\</span><span class="identifier">test</span> | |
9308 | </pre> | |
9309 | </div> | |
9310 | <div class="footnotes"> | |
9311 | <br><hr width="100" align="left"> | |
9312 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers.f0" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.synchronization.barriers.f0" class="para">2</a>] </sup> | |
9313 | The current implementation wakes fibers in FIFO order: the first | |
9314 | to call <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> | |
9315 | wakes first, and so forth. But it is perilous to rely on the order | |
9316 | in which the various fibers will reach the <code class="computeroutput"><span class="identifier">wait</span><span class="special">()</span></code> call. | |
9317 | </p></div> | |
9318 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.migration.f0" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.f0" class="para">3</a>] </sup> | |
9319 | The <span class="quote">“<span class="quote">main</span>”</span> fiber on each thread, that is, the fiber on | |
9320 | which the thread is launched, cannot migrate to any other thread. Also | |
9321 | <span class="bold"><strong>Boost.Fiber</strong></span> implicitly creates a dispatcher | |
9322 | fiber for each thread — this cannot migrate either. | |
9323 | </p></div> | |
9324 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.migration.f1" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.migration.f1" class="para">4</a>] </sup> | |
9325 | Of course it would be problematic to migrate a fiber that relies on | |
9326 | <a class="link" href="../../overview.html#thread_local_storage">thread-local storage</a>. | |
9327 | </p></div> | |
9328 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.f0" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.f0" class="para">5</a>] </sup> | |
9329 | This mechanism has been proposed as a conventional way to allow the | |
9330 | caller of an async function to specify completion handling: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf" target="_top">N4045</a>. | |
9331 | </p></div> | |
9332 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.f1" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.callbacks.f1" class="para">6</a>] </sup> | |
9333 | per <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4045.pdf" target="_top">N4045</a> | |
9334 | </p></div> | |
9335 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__return_values.f0" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.when_any.when_all_functionality.when_all__return_values.f0" class="para">7</a>] </sup> | |
9336 | We could have used either <a class="link" href="pooled_fixedsize.html#class_bounded_channel"> <code class="computeroutput">bounded_channel<></code></a> or | |
9337 | <a class="link" href="pooled_fixedsize.html#class_unbounded_channel"> <code class="computeroutput">unbounded_channel<></code></a>. We chose <code class="computeroutput"><span class="identifier">unbounded_channel</span><span class="special"><></span></code> | |
9338 | on the assumption that its simpler semantics imply a cheaper implementation. | |
9339 | </p></div> | |
9340 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.performance.f0" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.performance.f0" class="para">8</a>] </sup> | |
9341 | Intel Core2 Q6700, x86_64, 3GHz | |
9342 | </p></div> | |
9343 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.performance.f1" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.performance.f1" class="para">9</a>] </sup> | |
9344 | Intel Core2 Q6700, x86_64, 3GHz | |
9345 | </p></div> | |
9346 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.custom.f0" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.custom.f0" class="para">10</a>] </sup> | |
9347 | A previous version of the Fiber library implicitly tracked an int priority | |
9348 | for each fiber, even though the default scheduler ignored it. This | |
9349 | has been dropped, since the library now supports arbitrary scheduler-specific | |
9350 | fiber properties. | |
9351 | </p></div> | |
9352 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.f0" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.f0" class="para">11</a>] </sup> | |
9353 | <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4024.pdf" target="_top">'N4024: | |
9354 | Distinguishing coroutines and fibers'</a> | |
9355 | </p></div> | |
9356 | <div class="footnote"><p><sup>[<a name="ftn.fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.f1" href="#fiber.stack.protected_fixedsize.pooled_fixedsize.rationale.f1" class="para">12</a>] </sup> | |
9357 | David R. Butenhof <span class="quote">“<span class="quote">Programming with POSIX Threads</span>”</span> | |
9358 | </p></div> | |
9359 | </div> | |
9360 | </div> | |
9361 | <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> | |
9362 | <td align="left"></td> | |
9363 | <td align="right"><div class="copyright-footer">Copyright © 2013 Oliver Kowalke<p> | |
9364 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
9365 | file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) | |
9366 | </p> | |
9367 | </div></td> | |
9368 | </tr></table> | |
9369 | <hr> | |
9370 | <div class="spirit-nav"> | |
9371 | <a accesskey="p" href="../protected_fixedsize.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../protected_fixedsize.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a> | |
9372 | </div> | |
9373 | </body> | |
9374 | </html> |