]>
Commit | Line | Data |
---|---|---|
1 | [/ | |
2 | Copyright Oliver Kowalke 2013. | |
3 | Distributed under the Boost Software License, Version 1.0. | |
4 | (See accompanying file LICENSE_1_0.txt or copy at | |
5 | http://www.boost.org/LICENSE_1_0.txt | |
6 | ] | |
7 | ||
8 | [section:future Future] | |
9 | ||
10 | A future provides a mechanism to access the result of an asynchronous operation. | |
11 | ||
12 | [#shared_state] | |
13 | [heading shared state] | |
14 | ||
15 | Behind a [template_link promise] and its [template_link future] lies an | |
16 | unspecified object called their ['shared state]. The shared state is what will | |
17 | actually hold the async result (or the exception). | |
18 | ||
19 | The shared state is instantiated along with the [template_link promise]. | |
20 | ||
21 | Aside from its originating `promise<>`, a [template_link future] holds a | |
22 | unique reference to a particular shared state. However, multiple | |
23 | [template_link shared_future] instances can reference the same underlying | |
24 | shared state. | |
25 | ||
26 | As [template_link packaged_task] and [ns_function_link fibers..async] are | |
27 | implemented using [template_link promise], discussions of shared state apply | |
28 | to them as well. | |
29 | ||
30 | [#class_future_status] | |
31 | [heading Enumeration `future_status`] | |
32 | ||
33 | Timed wait-operations (__wait_for__ and __wait_until__) return the state of the future. | |
34 | ||
35 | enum class future_status { | |
36 | ready, | |
37 | timeout, | |
38 | deferred // not supported yet | |
39 | }; | |
40 | ||
41 | [heading `ready`] | |
42 | [variablelist | |
43 | [[Effects:] [The [link shared_state shared state] is ready.]] | |
44 | ] | |
45 | ||
46 | [heading `timeout`] | |
47 | [variablelist | |
48 | [[Effects:] [The [link shared_state shared state] did not become ready before timeout has passed.]] | |
49 | ] | |
50 | ||
51 | [note Deferred futures are not supported.] | |
52 | ||
53 | ||
54 | [template_heading future] | |
55 | ||
56 | A __future__ contains a [link shared_state shared state] which is not shared with any other future. | |
57 | ||
58 | #include <boost/fiber/future/future.hpp> | |
59 | ||
60 | namespace boost { | |
61 | namespace fibers { | |
62 | ||
63 | template< typename R > | |
64 | class future { | |
65 | public: | |
66 | future() noexcept; | |
67 | ||
68 | future( future const& other) = delete; | |
69 | ||
70 | future & operator=( future const& other) = delete; | |
71 | ||
72 | future( future && other) noexcept; | |
73 | ||
74 | future & operator=( future && other) noexcept; | |
75 | ||
76 | ~future(); | |
77 | ||
78 | bool valid() const noexcept; | |
79 | ||
80 | shared_future< R > share(); | |
81 | ||
82 | R get(); // member only of generic future template | |
83 | R & get(); // member only of future< R & > template specialization | |
84 | void get(); // member only of future< void > template specialization | |
85 | ||
86 | std::exception_ptr get_exception_ptr(); | |
87 | ||
88 | void wait() const; | |
89 | ||
90 | template< class Rep, class Period > | |
91 | future_status wait_for( | |
92 | std::chrono::duration< Rep, Period > const& timeout_duration) const; | |
93 | ||
94 | template< typename Clock, typename Duration > | |
95 | future_status wait_until( | |
96 | std::chrono::time_point< Clock, Duration > const& timeout_time) const; | |
97 | }; | |
98 | ||
99 | }} | |
100 | ||
101 | [heading Default constructor] | |
102 | ||
103 | future() noexcept; | |
104 | ||
105 | [template future_ctor_variablelist[xfuture] | |
106 | [variablelist | |
107 | [[Effects:] [Creates a [xfuture] with no [link shared_state shared state]. | |
108 | After construction `false == valid()`.]] | |
109 | [[Throws:] [Nothing.]] | |
110 | ] | |
111 | ] | |
112 | [future_ctor_variablelist future] | |
113 | ||
114 | [heading Move constructor] | |
115 | ||
116 | future( future && other) noexcept; | |
117 | ||
118 | [template future_move_copy_ctor_variablelist[xfuture post_valid] | |
119 | [variablelist | |
120 | [[Effects:] [Constructs a [xfuture] with the [link shared_state shared state] of other. | |
121 | After construction [post_valid].]] | |
122 | [[Throws:] [Nothing.]] | |
123 | ] | |
124 | ] | |
125 | [future_move_copy_ctor_variablelist future..`false == other.valid()`] | |
126 | ||
127 | [heading Destructor] | |
128 | ||
129 | ~future(); | |
130 | ||
131 | [template future_dtor_variablelist[xfuture end] | |
132 | [variablelist | |
133 | [[Effects:] [Destroys the [xfuture]; ownership is abandoned[end]]] | |
134 | [[Note:] [[`~[xfuture]()] does ['not] block the calling fiber.]] | |
135 | ] | |
136 | ] | |
137 | [future_dtor_variablelist future .] | |
138 | ||
139 | Consider a sequence such as: | |
140 | ||
141 | # instantiate [template_link promise] | |
142 | # obtain its `future<>` via [member_link promise..get_future] | |
143 | # launch [class_link fiber], capturing `promise<>` | |
144 | # destroy `future<>` | |
145 | # call [member_link promise..set_value] | |
146 | ||
147 | The final `set_value()` call succeeds, but the value is silently discarded: no | |
148 | additional `future<>` can be obtained from that `promise<>`. | |
149 | ||
150 | [operator_heading future..operator_assign..operator=] | |
151 | ||
152 | future & operator=( future && other) noexcept; | |
153 | ||
154 | [variablelist | |
155 | [[Effects:] [Moves the [link shared_state shared state] of other to `this`. | |
156 | After the assignment, `false == other.valid()`.]] | |
157 | [[Throws:] [Nothing.]] | |
158 | ] | |
159 | ||
160 | [template future_valid[xfuture] | |
161 | [member_heading [xfuture]..valid] | |
162 | ||
163 | bool valid() const noexcept; | |
164 | ||
165 | [variablelist | |
166 | [[Effects:] [Returns `true` if [xfuture] contains a [link shared_state shared state].]] | |
167 | [[Throws:] [Nothing.]] | |
168 | ] | |
169 | ] | |
170 | [future_valid future] | |
171 | ||
172 | [member_heading future..share] | |
173 | ||
174 | shared_future< R > share(); | |
175 | ||
176 | [variablelist | |
177 | [[Effects:] [Move the state to a __shared_future__.]] | |
178 | [[Returns:] [a __shared_future__ containing the [link shared_state shared | |
179 | state] formerly belonging to `*this`.]] | |
180 | [[Postcondition:] [`false == valid()`]] | |
181 | [[Throws:] [__future_error__ with error condition __no_state__.]] | |
182 | ] | |
183 | ||
184 | [template future_method_wait[end] Waits until [member_link promise..set_value] or | |
185 | [member_link promise..set_exception] is called[end]] | |
186 | ||
187 | [member_heading future..get] | |
188 | ||
189 | R get(); // member only of generic future template | |
190 | R & get(); // member only of future< R & > template specialization | |
191 | void get(); // member only of future< void > template specialization | |
192 | ||
193 | [template future_get_variablelist[] | |
194 | [variablelist | |
195 | [[Precondition:] [`true == valid()`]] | |
196 | [[Returns:] [[future_method_wait .] If [member_link promise..set_value] is | |
197 | called, returns the value. If [member_link promise..set_exception] is called, | |
198 | throws the indicated exception.]] | |
199 | [[Postcondition:] [`false == valid()`]] | |
200 | [[Throws:] [__future_error__ with error condition __no_state__, | |
201 | __broken_promise__. Any exception passed to | |
202 | `promise::set_exception()`.]] | |
203 | ] | |
204 | ] | |
205 | [future_get_variablelist] | |
206 | ||
207 | [template future_get_exception_ptr[xfuture] | |
208 | [member_heading [xfuture]..get_exception_ptr] | |
209 | ||
210 | std::exception_ptr get_exception_ptr(); | |
211 | ||
212 | [variablelist | |
213 | [[Precondition:] [`true == valid()`]] | |
214 | [[Returns:] [[future_method_wait .] If `set_value()` is called, returns a | |
215 | default-constructed `std::exception_ptr`. If `set_exception()` is called, | |
216 | returns the passed `std::exception_ptr`.]] | |
217 | [[Throws:] [__future_error__ with error condition __no_state__.]] | |
218 | [[Note:] [ `get_exception_ptr()` does ['not] invalidate the [`[xfuture]]. | |
219 | After calling `get_exception_ptr()`, you may still call [member_link | |
220 | [xfuture]..get].]] | |
221 | ] | |
222 | ] | |
223 | [future_get_exception_ptr future] | |
224 | ||
225 | [template future_wait_etc[xfuture] | |
226 | [member_heading [xfuture]..wait] | |
227 | ||
228 | void wait(); | |
229 | ||
230 | [variablelist | |
231 | [[Effects:] [[future_method_wait .]]] | |
232 | [[Throws:] [__future_error__ with error condition __no_state__.]] | |
233 | ] | |
234 | ||
235 | [template_member_heading [xfuture]..wait_for] | |
236 | ||
237 | template< class Rep, class Period > | |
238 | future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const; | |
239 | ||
240 | [variablelist | |
241 | [[Effects:] [[future_method_wait , or `timeout_duration` has passed.]]] | |
242 | [[Result:] [A `future_status` is returned indicating the reason for returning.]] | |
243 | [[Throws:] [__future_error__ with error condition __no_state__ or | |
244 | timeout-related exceptions.]] | |
245 | ] | |
246 | ||
247 | [template_member_heading [xfuture]..wait_until] | |
248 | ||
249 | template< typename Clock, typename Duration > | |
250 | future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const; | |
251 | ||
252 | [variablelist | |
253 | [[Effects:] [[future_method_wait , or `timeout_time` has passed.]]] | |
254 | [[Result:] [A `future_status` is returned indicating the reason for returning.]] | |
255 | [[Throws:] [__future_error__ with error condition __no_state__ or | |
256 | timeout-related exceptions.]] | |
257 | ] | |
258 | ] | |
259 | [future_wait_etc future] | |
260 | ||
261 | ||
262 | [template_heading shared_future] | |
263 | ||
264 | A __shared_future__ contains a [link shared_state shared state] which might be | |
265 | shared with other __shared_future__ instances. | |
266 | ||
267 | #include <boost/fiber/future/future.hpp> | |
268 | ||
269 | namespace boost { | |
270 | namespace fibers { | |
271 | ||
272 | template< typename R > | |
273 | class shared_future { | |
274 | public: | |
275 | shared_future() noexcept; | |
276 | ||
277 | ~shared_future(); | |
278 | ||
279 | shared_future( shared_future const& other); | |
280 | ||
281 | shared_future( future< R > && other) noexcept; | |
282 | ||
283 | shared_future( shared_future && other) noexcept; | |
284 | ||
285 | shared_future & operator=( shared_future && other) noexcept; | |
286 | ||
287 | shared_future & operator=( future< R > && other) noexcept; | |
288 | ||
289 | shared_future & operator=( shared_future const& other) noexcept; | |
290 | ||
291 | bool valid() const noexcept; | |
292 | ||
293 | R const& get(); // member only of generic shared_future template | |
294 | R & get(); // member only of shared_future< R & > template specialization | |
295 | void get(); // member only of shared_future< void > template specialization | |
296 | ||
297 | std::exception_ptr get_exception_ptr(); | |
298 | ||
299 | void wait() const; | |
300 | ||
301 | template< class Rep, class Period > | |
302 | future_status wait_for( | |
303 | std::chrono::duration< Rep, Period > const& timeout_duration) const; | |
304 | ||
305 | template< typename Clock, typename Duration > | |
306 | future_status wait_until( | |
307 | std::chrono::time_point< Clock, Duration > const& timeout_time) const; | |
308 | }; | |
309 | ||
310 | }} | |
311 | ||
312 | [heading Default constructor] | |
313 | ||
314 | shared_future(); | |
315 | ||
316 | [future_ctor_variablelist shared_future] | |
317 | ||
318 | [heading Move constructor] | |
319 | ||
320 | shared_future( future< R > && other) noexcept; | |
321 | shared_future( shared_future && other) noexcept; | |
322 | ||
323 | [future_move_copy_ctor_variablelist shared_future..`false == other.valid()`] | |
324 | ||
325 | [heading Copy constructor] | |
326 | ||
327 | shared_future( shared_future const& other) noexcept; | |
328 | ||
329 | [future_move_copy_ctor_variablelist shared_future..`other.valid()` is unchanged] | |
330 | ||
331 | [heading Destructor] | |
332 | ||
333 | ~shared_future(); | |
334 | ||
335 | [future_dtor_variablelist shared_future.. if not shared.] | |
336 | ||
337 | [operator_heading shared_future..operator_assign..operator=] | |
338 | ||
339 | shared_future & operator=( future< R > && other) noexcept; | |
340 | shared_future & operator=( shared_future && other) noexcept; | |
341 | shared_future & operator=( shared_future const& other) noexcept; | |
342 | ||
343 | [variablelist | |
344 | [[Effects:] [Moves or copies the [link shared_state shared state] of other to | |
345 | `this`. After the assignment, the state of `other.valid()` depends on which | |
346 | overload was invoked: unchanged for the overload accepting `shared_future | |
347 | const&`, otherwise `false`.]] | |
348 | [[Throws:] [Nothing.]] | |
349 | ] | |
350 | ||
351 | [future_valid shared_future] | |
352 | ||
353 | [member_heading shared_future..get] | |
354 | ||
355 | R const& get(); // member only of generic shared_future template | |
356 | R & get(); // member only of shared_future< R & > template specialization | |
357 | void get(); // member only of shared_future< void > template specialization | |
358 | ||
359 | [future_get_variablelist] | |
360 | ||
361 | [future_get_exception_ptr shared_future] | |
362 | ||
363 | [future_wait_etc shared_future] | |
364 | ||
365 | [ns_function_heading fibers..async] | |
366 | ||
367 | #include <boost/fiber/future/async.hpp> | |
368 | ||
369 | namespace boost { | |
370 | namespace fibers { | |
371 | ||
372 | template< class Function, class ... Args > | |
373 | future< | |
374 | std::result_of_t< | |
375 | std::decay_t< Function >( std::decay_t< Args > ... ) | |
376 | > | |
377 | > | |
378 | async( Function && fn, Args && ... args); | |
379 | ||
380 | template< class Function, class ... Args > | |
381 | future< | |
382 | std::result_of_t< | |
383 | std::decay_t< Function >( std::decay_t< Args > ... ) | |
384 | > | |
385 | > | |
386 | async( ``[link class_launch `launch`]`` policy, Function && fn, Args && ... args); | |
387 | ||
388 | template< typename __StackAllocator__, class Function, class ... Args > | |
389 | future< | |
390 | std::result_of_t< | |
391 | std::decay_t< Function >( std::decay_t< Args > ... ) | |
392 | > | |
393 | > | |
394 | async( ``[link class_launch `launch`]`` policy, __allocator_arg_t__, __StackAllocator__ salloc, | |
395 | Function && fn, Args && ... args); | |
396 | ||
397 | }} | |
398 | ||
399 | [variablelist | |
400 | [[Effects:] [Executes `fn` in a [class_link fiber] and returns an associated | |
401 | [template_link future].]] | |
402 | [[Result:] [``future< | |
403 | std::result_of_t< | |
404 | std::decay_t< Function >( std::decay_t< Args > ... ) | |
405 | > | |
406 | >`` representing the [link | |
407 | shared_state shared state] associated with the asynchronous execution of | |
408 | `fn`.]] | |
409 | [[Throws:] [__fiber_error__ or __future_error__ if an error occurs.]] | |
410 | [[Notes:] [The overloads accepting __allocator_arg_t__ use the passed | |
411 | __StackAllocator__ when constructing the launched `fiber`. The overloads | |
412 | accepting [class_link launch] use the passed `launch` when | |
413 | constructing the launched `fiber`. The default `launch` is `post`, as | |
414 | for the `fiber` constructor.]] | |
415 | ] | |
416 | ||
417 | [note Deferred futures are not supported.] | |
418 | ||
419 | [endsect] |