]>
Commit | Line | Data |
---|---|---|
c910ceff JW |
1 | // <future> -*- C++ -*- |
2 | ||
7a0269de | 3 | // Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. |
c910ceff JW |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // Under Section 7 of GPL version 3, you are granted additional | |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
24 | ||
f910786b | 25 | /** @file include/future |
c910ceff JW |
26 | * This is a Standard C++ Library header. |
27 | */ | |
28 | ||
29 | #ifndef _GLIBCXX_FUTURE | |
30 | #define _GLIBCXX_FUTURE 1 | |
31 | ||
32 | #pragma GCC system_header | |
33 | ||
34 | #ifndef __GXX_EXPERIMENTAL_CXX0X__ | |
ab65a4c7 | 35 | # include <bits/c++0x_warning.h> |
c910ceff JW |
36 | #else |
37 | ||
38 | #include <functional> | |
39 | #include <memory> | |
40 | #include <mutex> | |
b3eed6fe | 41 | #include <thread> |
c910ceff JW |
42 | #include <condition_variable> |
43 | #include <system_error> | |
44 | #include <exception> | |
afd88205 | 45 | #include <atomic> |
abcd7e08 | 46 | #include <bits/functexcept.h> |
c910ceff | 47 | |
12ffa228 BK |
48 | namespace std _GLIBCXX_VISIBILITY(default) |
49 | { | |
50 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
53dc5044 | 51 | |
c910ceff JW |
52 | /** |
53 | * @defgroup futures Futures | |
54 | * @ingroup concurrency | |
55 | * | |
56 | * Classes for futures support. | |
57 | * @{ | |
58 | */ | |
59 | ||
60 | /// Error code for futures | |
61 | enum class future_errc | |
b3eed6fe JW |
62 | { |
63 | broken_promise, | |
64 | future_already_retrieved, | |
65 | promise_already_satisfied, | |
66 | no_state | |
67 | }; | |
c910ceff | 68 | |
94a86be0 | 69 | /// Specialization. |
c910ceff JW |
70 | template<> |
71 | struct is_error_code_enum<future_errc> : public true_type { }; | |
72 | ||
73 | /// Points to a statically-allocated object derived from error_category. | |
94a86be0 BK |
74 | const error_category& |
75 | future_category(); | |
c910ceff | 76 | |
94a86be0 BK |
77 | /// Overload for make_error_code. |
78 | inline error_code | |
79 | make_error_code(future_errc __errc) | |
80 | { return error_code(static_cast<int>(__errc), future_category()); } | |
c910ceff | 81 | |
94a86be0 BK |
82 | /// Overload for make_error_condition. |
83 | inline error_condition | |
84 | make_error_condition(future_errc __errc) | |
85 | { return error_condition(static_cast<int>(__errc), future_category()); } | |
c910ceff | 86 | |
8d1b99e2 BK |
87 | /** |
88 | * @brief Exception type thrown by futures. | |
89 | * @ingroup exceptions | |
90 | */ | |
c910ceff JW |
91 | class future_error : public logic_error |
92 | { | |
c36abf03 | 93 | error_code _M_code; |
8d1b99e2 | 94 | |
c910ceff | 95 | public: |
b3eed6fe JW |
96 | explicit future_error(error_code __ec) |
97 | : logic_error("std::future_error"), _M_code(__ec) | |
c910ceff JW |
98 | { } |
99 | ||
8d1b99e2 | 100 | virtual ~future_error() throw(); |
c910ceff | 101 | |
8d1b99e2 BK |
102 | virtual const char* |
103 | what() const throw(); | |
c910ceff | 104 | |
8d1b99e2 BK |
105 | const error_code& |
106 | code() const throw() { return _M_code; } | |
c910ceff JW |
107 | }; |
108 | ||
3259554a | 109 | // Forward declarations. |
c36abf03 | 110 | template<typename _Res> |
b3eed6fe | 111 | class future; |
3259554a | 112 | |
c36abf03 | 113 | template<typename _Res> |
3259554a BK |
114 | class shared_future; |
115 | ||
b3eed6fe JW |
116 | template<typename _Res> |
117 | class atomic_future; | |
118 | ||
119 | template<typename _Signature> | |
3259554a BK |
120 | class packaged_task; |
121 | ||
c36abf03 | 122 | template<typename _Res> |
3259554a BK |
123 | class promise; |
124 | ||
94a86be0 BK |
125 | /// Launch code for futures |
126 | enum class launch | |
127 | { | |
128 | any, | |
129 | async, | |
130 | sync | |
131 | }; | |
132 | ||
133 | /// Status code for futures | |
134 | enum class future_status | |
135 | { | |
136 | ready, | |
137 | timeout, | |
138 | deferred | |
139 | }; | |
b3eed6fe JW |
140 | |
141 | template<typename _Fn, typename... _Args> | |
73c5c5bb | 142 | future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe JW |
143 | async(launch __policy, _Fn&& __fn, _Args&&... __args); |
144 | ||
145 | template<typename _Fn, typename... _Args> | |
73c5c5bb JW |
146 | typename |
147 | enable_if<!is_same<typename decay<_Fn>::type, launch>::value, | |
148 | future<decltype(std::declval<_Fn>()(std::declval<_Args>()...))> | |
149 | >::type | |
b3eed6fe JW |
150 | async(_Fn&& __fn, _Args&&... __args); |
151 | ||
41ca4246 BK |
152 | #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \ |
153 | && defined(_GLIBCXX_ATOMIC_BUILTINS_4) | |
154 | ||
c36abf03 BK |
155 | /// Base class and enclosing scope. |
156 | struct __future_base | |
c910ceff | 157 | { |
c36abf03 BK |
158 | /// Base class for results. |
159 | struct _Result_base | |
160 | { | |
161 | exception_ptr _M_error; | |
c910ceff | 162 | |
c36abf03 BK |
163 | _Result_base(const _Result_base&) = delete; |
164 | _Result_base& operator=(const _Result_base&) = delete; | |
c910ceff | 165 | |
b3eed6fe | 166 | // _M_destroy() allows derived classes to control deallocation |
c36abf03 | 167 | virtual void _M_destroy() = 0; |
c910ceff | 168 | |
c36abf03 BK |
169 | struct _Deleter |
170 | { | |
171 | void operator()(_Result_base* __fr) const { __fr->_M_destroy(); } | |
172 | }; | |
c910ceff | 173 | |
c36abf03 | 174 | protected: |
e9599233 BK |
175 | _Result_base(); |
176 | virtual ~_Result_base(); | |
c36abf03 | 177 | }; |
20f2653e | 178 | |
c36abf03 BK |
179 | /// Result. |
180 | template<typename _Res> | |
181 | struct _Result : _Result_base | |
182 | { | |
183 | private: | |
184 | typedef alignment_of<_Res> __a_of; | |
185 | typedef aligned_storage<sizeof(_Res), __a_of::value> __align_storage; | |
186 | typedef typename __align_storage::type __align_type; | |
187 | ||
188 | __align_type _M_storage; | |
189 | bool _M_initialized; | |
190 | ||
191 | public: | |
192 | _Result() : _M_initialized() { } | |
193 | ||
194 | ~_Result() | |
195 | { | |
196 | if (_M_initialized) | |
197 | _M_value().~_Res(); | |
198 | } | |
199 | ||
200 | // Return lvalue, future will add const or rvalue-reference | |
201 | _Res& | |
202 | _M_value() { return *static_cast<_Res*>(_M_addr()); } | |
203 | ||
204 | void | |
205 | _M_set(const _Res& __res) | |
206 | { | |
207 | ::new (_M_addr()) _Res(__res); | |
208 | _M_initialized = true; | |
209 | } | |
210 | ||
211 | void | |
212 | _M_set(_Res&& __res) | |
213 | { | |
abcd7e08 | 214 | ::new (_M_addr()) _Res(std::move(__res)); |
c36abf03 BK |
215 | _M_initialized = true; |
216 | } | |
217 | ||
218 | private: | |
219 | void _M_destroy() { delete this; } | |
220 | ||
221 | void* _M_addr() { return static_cast<void*>(&_M_storage); } | |
c910ceff JW |
222 | }; |
223 | ||
c36abf03 BK |
224 | // TODO: use template alias when available |
225 | /* | |
226 | template<typename _Res> | |
227 | using _Ptr = unique_ptr<_Res, _Result_base::_Deleter>; | |
228 | */ | |
229 | /// A unique_ptr based on the instantiating type. | |
230 | template<typename _Res> | |
231 | struct _Ptr | |
232 | { | |
233 | typedef unique_ptr<_Res, _Result_base::_Deleter> type; | |
234 | }; | |
c910ceff | 235 | |
b3eed6fe JW |
236 | /// Result_alloc. |
237 | template<typename _Res, typename _Alloc> | |
0fd76d8e | 238 | struct _Result_alloc : _Result<_Res>, _Alloc |
b3eed6fe JW |
239 | { |
240 | typedef typename _Alloc::template rebind<_Result_alloc>::other | |
241 | __allocator_type; | |
242 | ||
243 | explicit | |
0fd76d8e | 244 | _Result_alloc(const _Alloc& __a) : _Result<_Res>(), _Alloc(__a) |
b3eed6fe JW |
245 | { } |
246 | ||
247 | private: | |
248 | void _M_destroy() | |
249 | { | |
0fd76d8e | 250 | __allocator_type __a(*this); |
b3eed6fe JW |
251 | __a.destroy(this); |
252 | __a.deallocate(this, 1); | |
253 | } | |
135a0d0a | 254 | }; |
b3eed6fe JW |
255 | |
256 | template<typename _Res, typename _Allocator> | |
257 | static typename _Ptr<_Result_alloc<_Res, _Allocator>>::type | |
258 | _S_allocate_result(const _Allocator& __a) | |
259 | { | |
260 | typedef _Result_alloc<_Res, _Allocator> __result_type; | |
261 | typename __result_type::__allocator_type __a2(__a); | |
262 | __result_type* __p = __a2.allocate(1); | |
263 | __try | |
135a0d0a | 264 | { |
b3eed6fe JW |
265 | __a2.construct(__p, __a); |
266 | } | |
267 | __catch(...) | |
268 | { | |
269 | __a2.deallocate(__p, 1); | |
270 | __throw_exception_again; | |
271 | } | |
272 | return typename _Ptr<__result_type>::type(__p); | |
273 | } | |
b3eed6fe | 274 | |
c910ceff | 275 | |
e9599233 BK |
276 | /// Base class for state between a promise and one or more |
277 | /// associated futures. | |
278 | class _State_base | |
c910ceff | 279 | { |
c36abf03 | 280 | typedef _Ptr<_Result_base>::type _Ptr_type; |
c910ceff | 281 | |
c36abf03 BK |
282 | _Ptr_type _M_result; |
283 | mutex _M_mutex; | |
284 | condition_variable _M_cond; | |
285 | atomic_flag _M_retrieved; | |
b3eed6fe | 286 | once_flag _M_once; |
c910ceff | 287 | |
c36abf03 | 288 | public: |
e9599233 BK |
289 | _State_base() : _M_result(), _M_retrieved(ATOMIC_FLAG_INIT) { } |
290 | _State_base(const _State_base&) = delete; | |
291 | _State_base& operator=(const _State_base&) = delete; | |
292 | virtual ~_State_base(); | |
c910ceff | 293 | |
c36abf03 BK |
294 | _Result_base& |
295 | wait() | |
c910ceff | 296 | { |
b3eed6fe | 297 | _M_run_deferred(); |
c36abf03 BK |
298 | unique_lock<mutex> __lock(_M_mutex); |
299 | if (!_M_ready()) | |
e9599233 | 300 | _M_cond.wait(__lock, std::bind<bool>(&_State_base::_M_ready, this)); |
c36abf03 | 301 | return *_M_result; |
c910ceff | 302 | } |
c910ceff | 303 | |
c36abf03 BK |
304 | template<typename _Rep, typename _Period> |
305 | bool | |
306 | wait_for(const chrono::duration<_Rep, _Period>& __rel) | |
307 | { | |
308 | unique_lock<mutex> __lock(_M_mutex); | |
e9599233 | 309 | auto __bound = std::bind<bool>(&_State_base::_M_ready, this); |
c36abf03 BK |
310 | return _M_ready() || _M_cond.wait_for(__lock, __rel, __bound); |
311 | } | |
c910ceff | 312 | |
c36abf03 BK |
313 | template<typename _Clock, typename _Duration> |
314 | bool | |
315 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) | |
316 | { | |
317 | unique_lock<mutex> __lock(_M_mutex); | |
e9599233 | 318 | auto __bound = std::bind<bool>(&_State_base::_M_ready, this); |
c36abf03 BK |
319 | return _M_ready() || _M_cond.wait_until(__lock, __abs, __bound); |
320 | } | |
c910ceff | 321 | |
c36abf03 | 322 | void |
b3eed6fe | 323 | _M_set_result(function<_Ptr_type()> __res, bool __ignore_failure = false) |
c910ceff | 324 | { |
b3eed6fe JW |
325 | bool __set = __ignore_failure; |
326 | // all calls to this function are serialized, | |
327 | // side-effects of invoking __res only happen once | |
e9599233 | 328 | call_once(_M_once, &_State_base::_M_do_set, this, ref(__res), |
b3eed6fe JW |
329 | ref(__set)); |
330 | if (!__set) | |
331 | __throw_future_error(int(future_errc::promise_already_satisfied)); | |
c910ceff JW |
332 | } |
333 | ||
c910ceff | 334 | void |
c36abf03 | 335 | _M_break_promise(_Ptr_type __res) |
c910ceff | 336 | { |
c36abf03 BK |
337 | if (static_cast<bool>(__res)) |
338 | { | |
b3eed6fe | 339 | error_code __ec(make_error_code(future_errc::broken_promise)); |
c36abf03 BK |
340 | __res->_M_error = copy_exception(future_error(__ec)); |
341 | { | |
342 | lock_guard<mutex> __lock(_M_mutex); | |
343 | _M_result.swap(__res); | |
344 | } | |
345 | _M_cond.notify_all(); | |
346 | } | |
c910ceff JW |
347 | } |
348 | ||
b3eed6fe | 349 | // Called when this object is passed to a future. |
c910ceff | 350 | void |
c36abf03 | 351 | _M_set_retrieved_flag() |
c910ceff | 352 | { |
c36abf03 BK |
353 | if (_M_retrieved.test_and_set()) |
354 | __throw_future_error(int(future_errc::future_already_retrieved)); | |
c910ceff JW |
355 | } |
356 | ||
b3eed6fe JW |
357 | template<typename _Res, typename _Arg> |
358 | struct _Setter; | |
359 | ||
360 | // set lvalues | |
361 | template<typename _Res, typename _Arg> | |
362 | struct _Setter<_Res, _Arg&> | |
363 | { | |
364 | // check this is only used by promise<R>::set_value(const R&) | |
365 | // or promise<R>::set_value(R&) | |
366 | static_assert(is_same<_Res, _Arg&>::value // promise<R&> | |
367 | || is_same<const _Res, _Arg>::value, // promise<R> | |
368 | "Invalid specialisation"); | |
369 | ||
370 | typename promise<_Res>::_Ptr_type operator()() | |
371 | { | |
e9599233 | 372 | _State_base::_S_check(_M_promise->_M_future); |
b3eed6fe JW |
373 | _M_promise->_M_storage->_M_set(_M_arg); |
374 | return std::move(_M_promise->_M_storage); | |
375 | } | |
376 | promise<_Res>* _M_promise; | |
377 | _Arg& _M_arg; | |
378 | }; | |
379 | ||
380 | // set rvalues | |
381 | template<typename _Res> | |
382 | struct _Setter<_Res, _Res&&> | |
383 | { | |
384 | typename promise<_Res>::_Ptr_type operator()() | |
385 | { | |
e9599233 | 386 | _State_base::_S_check(_M_promise->_M_future); |
b3eed6fe JW |
387 | _M_promise->_M_storage->_M_set(std::move(_M_arg)); |
388 | return std::move(_M_promise->_M_storage); | |
389 | } | |
390 | promise<_Res>* _M_promise; | |
391 | _Res& _M_arg; | |
392 | }; | |
393 | ||
394 | struct __exception_ptr_tag { }; | |
395 | ||
396 | // set exceptions | |
397 | template<typename _Res> | |
398 | struct _Setter<_Res, __exception_ptr_tag> | |
399 | { | |
400 | typename promise<_Res>::_Ptr_type operator()() | |
401 | { | |
e9599233 | 402 | _State_base::_S_check(_M_promise->_M_future); |
b3eed6fe JW |
403 | _M_promise->_M_storage->_M_error = _M_ex; |
404 | return std::move(_M_promise->_M_storage); | |
405 | } | |
406 | ||
407 | promise<_Res>* _M_promise; | |
408 | exception_ptr& _M_ex; | |
409 | }; | |
410 | ||
411 | template<typename _Res, typename _Arg> | |
412 | static _Setter<_Res, _Arg&&> | |
413 | __setter(promise<_Res>* __prom, _Arg&& __arg) | |
414 | { | |
415 | return _Setter<_Res, _Arg&&>{ __prom, __arg }; | |
416 | } | |
417 | ||
418 | template<typename _Res> | |
419 | static _Setter<_Res, __exception_ptr_tag> | |
420 | __setter(exception_ptr& __ex, promise<_Res>* __prom) | |
421 | { | |
422 | return _Setter<_Res, __exception_ptr_tag>{ __prom, __ex }; | |
423 | } | |
424 | ||
425 | static _Setter<void, void> | |
426 | __setter(promise<void>* __prom); | |
427 | ||
428 | template<typename _Tp> | |
429 | static bool | |
430 | _S_check(const shared_ptr<_Tp>& __p) | |
431 | { | |
432 | if (!static_cast<bool>(__p)) | |
433 | __throw_future_error((int)future_errc::no_state); | |
434 | } | |
435 | ||
c910ceff | 436 | private: |
b3eed6fe JW |
437 | void |
438 | _M_do_set(function<_Ptr_type()>& __f, bool& __set) | |
c36abf03 | 439 | { |
b3eed6fe JW |
440 | _Ptr_type __res = __f(); |
441 | { | |
442 | lock_guard<mutex> __lock(_M_mutex); | |
443 | _M_result.swap(__res); | |
444 | } | |
445 | _M_cond.notify_all(); | |
446 | __set = true; | |
c36abf03 | 447 | } |
c910ceff | 448 | |
c36abf03 | 449 | bool _M_ready() const { return static_cast<bool>(_M_result); } |
b3eed6fe JW |
450 | |
451 | virtual void _M_run_deferred() { } | |
c910ceff | 452 | }; |
b3eed6fe JW |
453 | |
454 | template<typename _Res> | |
455 | class _Deferred_state; | |
456 | ||
457 | template<typename _Res> | |
458 | class _Async_state; | |
459 | ||
460 | template<typename _Signature> | |
461 | class _Task_state; | |
462 | ||
463 | template<typename _StateT, typename _Res = typename _StateT::_Res_type> | |
464 | struct _Task_setter; | |
c36abf03 | 465 | }; |
c910ceff | 466 | |
c36abf03 BK |
467 | /// Partial specialization for reference types. |
468 | template<typename _Res> | |
469 | struct __future_base::_Result<_Res&> : __future_base::_Result_base | |
470 | { | |
471 | _Result() : _M_value_ptr() { } | |
c910ceff | 472 | |
b3eed6fe JW |
473 | void _M_set(_Res& __res) { _M_value_ptr = &__res; } |
474 | ||
475 | _Res& _M_get() { return *_M_value_ptr; } | |
476 | ||
477 | private: | |
c36abf03 BK |
478 | _Res* _M_value_ptr; |
479 | ||
c910ceff JW |
480 | void _M_destroy() { delete this; } |
481 | }; | |
482 | ||
c36abf03 | 483 | /// Explicit specialization for void. |
c910ceff | 484 | template<> |
c36abf03 | 485 | struct __future_base::_Result<void> : __future_base::_Result_base |
c910ceff | 486 | { |
c36abf03 | 487 | private: |
c910ceff JW |
488 | void _M_destroy() { delete this; } |
489 | }; | |
490 | ||
c36abf03 | 491 | |
b3eed6fe | 492 | /// Common implementation for future and shared_future. |
c36abf03 BK |
493 | template<typename _Res> |
494 | class __basic_future : public __future_base | |
c910ceff | 495 | { |
c36abf03 | 496 | protected: |
e9599233 | 497 | typedef shared_ptr<_State_base> __state_type; |
c36abf03 BK |
498 | typedef __future_base::_Result<_Res>& __result_type; |
499 | ||
500 | private: | |
501 | __state_type _M_state; | |
502 | ||
c910ceff | 503 | public: |
c36abf03 BK |
504 | // Disable copying. |
505 | __basic_future(const __basic_future&) = delete; | |
506 | __basic_future& operator=(const __basic_future&) = delete; | |
c910ceff | 507 | |
c36abf03 | 508 | bool |
b3eed6fe | 509 | valid() const { return static_cast<bool>(_M_state); } |
c910ceff | 510 | |
c36abf03 | 511 | void |
5262c72a JW |
512 | wait() const |
513 | { | |
e9599233 | 514 | _State_base::_S_check(_M_state); |
5262c72a JW |
515 | _M_state->wait(); |
516 | } | |
c910ceff JW |
517 | |
518 | template<typename _Rep, typename _Period> | |
519 | bool | |
520 | wait_for(const chrono::duration<_Rep, _Period>& __rel) const | |
5262c72a | 521 | { |
e9599233 | 522 | _State_base::_S_check(_M_state); |
5262c72a JW |
523 | return _M_state->wait_for(__rel); |
524 | } | |
c910ceff JW |
525 | |
526 | template<typename _Clock, typename _Duration> | |
527 | bool | |
528 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) const | |
5262c72a | 529 | { |
e9599233 | 530 | _State_base::_S_check(_M_state); |
5262c72a JW |
531 | return _M_state->wait_until(__abs); |
532 | } | |
c910ceff JW |
533 | |
534 | protected: | |
c36abf03 BK |
535 | /// Wait for the state to be ready and rethrow any stored exception |
536 | __result_type | |
c910ceff JW |
537 | _M_get_result() |
538 | { | |
e9599233 | 539 | _State_base::_S_check(_M_state); |
b3eed6fe | 540 | _Result_base& __res = _M_state->wait(); |
c910ceff JW |
541 | if (!(__res._M_error == 0)) |
542 | rethrow_exception(__res._M_error); | |
c36abf03 | 543 | return static_cast<__result_type>(__res); |
c910ceff JW |
544 | } |
545 | ||
b3eed6fe JW |
546 | void _M_swap(__basic_future& __that) |
547 | { | |
548 | _M_state.swap(__that._M_state); | |
549 | } | |
550 | ||
551 | // Construction of a future by promise::get_future() | |
c910ceff | 552 | explicit |
c36abf03 | 553 | __basic_future(const __state_type& __state) : _M_state(__state) |
c910ceff | 554 | { |
e9599233 | 555 | _State_base::_S_check(_M_state); |
b3eed6fe | 556 | _M_state->_M_set_retrieved_flag(); |
c910ceff JW |
557 | } |
558 | ||
c36abf03 | 559 | // Copy construction from a shared_future |
c910ceff | 560 | explicit |
c36abf03 | 561 | __basic_future(const shared_future<_Res>&); |
c910ceff | 562 | |
b3eed6fe | 563 | // Move construction from a shared_future |
c910ceff | 564 | explicit |
b3eed6fe JW |
565 | __basic_future(shared_future<_Res>&&); |
566 | ||
567 | // Move construction from a future | |
568 | explicit | |
569 | __basic_future(future<_Res>&&); | |
570 | ||
85db9dcc | 571 | constexpr __basic_future() : _M_state() { } |
b3eed6fe JW |
572 | |
573 | struct _Reset | |
574 | { | |
575 | explicit _Reset(__basic_future& __fut) : _M_fut(__fut) { } | |
576 | ~_Reset() { _M_fut._M_state.reset(); } | |
577 | __basic_future& _M_fut; | |
578 | }; | |
c910ceff JW |
579 | }; |
580 | ||
c36abf03 | 581 | |
b3eed6fe | 582 | /// Primary template for future. |
c36abf03 | 583 | template<typename _Res> |
b3eed6fe | 584 | class future : public __basic_future<_Res> |
c910ceff | 585 | { |
c36abf03 | 586 | friend class promise<_Res>; |
b3eed6fe JW |
587 | template<typename> friend class packaged_task; |
588 | template<typename _Fn, typename... _Args> | |
73c5c5bb | 589 | friend future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe | 590 | async(launch, _Fn&&, _Args&&...); |
c36abf03 BK |
591 | |
592 | typedef __basic_future<_Res> _Base_type; | |
593 | typedef typename _Base_type::__state_type __state_type; | |
c36abf03 BK |
594 | |
595 | explicit | |
b3eed6fe | 596 | future(const __state_type& __state) : _Base_type(__state) { } |
c910ceff JW |
597 | |
598 | public: | |
85db9dcc | 599 | constexpr future() : _Base_type() { } |
b3eed6fe | 600 | |
c910ceff | 601 | /// Move constructor |
b3eed6fe | 602 | future(future&& __uf) : _Base_type(std::move(__uf)) { } |
c910ceff | 603 | |
c36abf03 | 604 | // Disable copying |
b3eed6fe JW |
605 | future(const future&) = delete; |
606 | future& operator=(const future&) = delete; | |
607 | ||
608 | future& operator=(future&& __fut) | |
609 | { | |
610 | future(std::move(__fut))._M_swap(*this); | |
611 | return *this; | |
612 | } | |
c910ceff | 613 | |
c36abf03 | 614 | /// Retrieving the value |
b3eed6fe | 615 | _Res |
c910ceff | 616 | get() |
b3eed6fe JW |
617 | { |
618 | typename _Base_type::_Reset __reset(*this); | |
619 | return std::move(this->_M_get_result()._M_value()); | |
620 | } | |
e3e08a1d JW |
621 | |
622 | shared_future<_Res> share(); | |
c910ceff JW |
623 | }; |
624 | ||
b3eed6fe | 625 | /// Partial specialization for future<R&> |
c36abf03 | 626 | template<typename _Res> |
b3eed6fe | 627 | class future<_Res&> : public __basic_future<_Res&> |
c910ceff | 628 | { |
c36abf03 | 629 | friend class promise<_Res&>; |
b3eed6fe JW |
630 | template<typename> friend class packaged_task; |
631 | template<typename _Fn, typename... _Args> | |
73c5c5bb | 632 | friend future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe | 633 | async(launch, _Fn&&, _Args&&...); |
c36abf03 BK |
634 | |
635 | typedef __basic_future<_Res&> _Base_type; | |
636 | typedef typename _Base_type::__state_type __state_type; | |
637 | ||
638 | explicit | |
b3eed6fe | 639 | future(const __state_type& __state) : _Base_type(__state) { } |
c36abf03 | 640 | |
c910ceff | 641 | public: |
85db9dcc | 642 | constexpr future() : _Base_type() { } |
b3eed6fe | 643 | |
c910ceff | 644 | /// Move constructor |
b3eed6fe | 645 | future(future&& __uf) : _Base_type(std::move(__uf)) { } |
c910ceff | 646 | |
c36abf03 | 647 | // Disable copying |
b3eed6fe JW |
648 | future(const future&) = delete; |
649 | future& operator=(const future&) = delete; | |
650 | ||
651 | future& operator=(future&& __fut) | |
652 | { | |
653 | future(std::move(__fut))._M_swap(*this); | |
654 | return *this; | |
655 | } | |
c910ceff | 656 | |
c36abf03 BK |
657 | /// Retrieving the value |
658 | _Res& | |
b3eed6fe JW |
659 | get() |
660 | { | |
661 | typename _Base_type::_Reset __reset(*this); | |
662 | return this->_M_get_result()._M_get(); | |
663 | } | |
e3e08a1d JW |
664 | |
665 | shared_future<_Res&> share(); | |
c36abf03 | 666 | }; |
c910ceff | 667 | |
b3eed6fe | 668 | /// Explicit specialization for future<void> |
c36abf03 | 669 | template<> |
b3eed6fe | 670 | class future<void> : public __basic_future<void> |
c36abf03 BK |
671 | { |
672 | friend class promise<void>; | |
b3eed6fe JW |
673 | template<typename> friend class packaged_task; |
674 | template<typename _Fn, typename... _Args> | |
73c5c5bb | 675 | friend future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe | 676 | async(launch, _Fn&&, _Args&&...); |
c910ceff | 677 | |
c36abf03 BK |
678 | typedef __basic_future<void> _Base_type; |
679 | typedef typename _Base_type::__state_type __state_type; | |
c910ceff JW |
680 | |
681 | explicit | |
b3eed6fe | 682 | future(const __state_type& __state) : _Base_type(__state) { } |
c910ceff | 683 | |
c910ceff | 684 | public: |
85db9dcc | 685 | constexpr future() : _Base_type() { } |
b3eed6fe | 686 | |
c910ceff | 687 | /// Move constructor |
b3eed6fe | 688 | future(future&& __uf) : _Base_type(std::move(__uf)) { } |
c910ceff | 689 | |
c36abf03 | 690 | // Disable copying |
b3eed6fe JW |
691 | future(const future&) = delete; |
692 | future& operator=(const future&) = delete; | |
693 | ||
694 | future& operator=(future&& __fut) | |
695 | { | |
696 | future(std::move(__fut))._M_swap(*this); | |
697 | return *this; | |
698 | } | |
c910ceff | 699 | |
c36abf03 BK |
700 | /// Retrieving the value |
701 | void | |
b3eed6fe JW |
702 | get() |
703 | { | |
704 | typename _Base_type::_Reset __reset(*this); | |
705 | this->_M_get_result(); | |
706 | } | |
e3e08a1d JW |
707 | |
708 | shared_future<void> share(); | |
c910ceff JW |
709 | }; |
710 | ||
c36abf03 BK |
711 | |
712 | /// Primary template for shared_future. | |
713 | template<typename _Res> | |
714 | class shared_future : public __basic_future<_Res> | |
c910ceff | 715 | { |
c36abf03 BK |
716 | typedef __basic_future<_Res> _Base_type; |
717 | ||
c910ceff | 718 | public: |
85db9dcc | 719 | constexpr shared_future() : _Base_type() { } |
b3eed6fe | 720 | |
c910ceff JW |
721 | /// Copy constructor |
722 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
723 | ||
b3eed6fe JW |
724 | /// Construct from a future rvalue |
725 | shared_future(future<_Res>&& __uf) | |
c910ceff JW |
726 | : _Base_type(std::move(__uf)) |
727 | { } | |
728 | ||
b3eed6fe JW |
729 | /// Construct from a shared_future rvalue |
730 | shared_future(shared_future&& __sf) | |
731 | : _Base_type(std::move(__sf)) | |
732 | { } | |
733 | ||
734 | shared_future& operator=(const shared_future& __sf) | |
735 | { | |
736 | shared_future(__sf)._M_swap(*this); | |
737 | return *this; | |
738 | } | |
739 | ||
740 | shared_future& operator=(shared_future&& __sf) | |
741 | { | |
742 | shared_future(std::move(__sf))._M_swap(*this); | |
743 | return *this; | |
744 | } | |
c910ceff | 745 | |
c36abf03 BK |
746 | /// Retrieving the value |
747 | const _Res& | |
c910ceff | 748 | get() |
b3eed6fe | 749 | { |
c36abf03 BK |
750 | typename _Base_type::__result_type __r = this->_M_get_result(); |
751 | _Res& __rs(__r._M_value()); | |
752 | return __rs; | |
753 | } | |
c910ceff JW |
754 | }; |
755 | ||
c36abf03 BK |
756 | /// Partial specialization for shared_future<R&> |
757 | template<typename _Res> | |
758 | class shared_future<_Res&> : public __basic_future<_Res&> | |
c910ceff | 759 | { |
c36abf03 BK |
760 | typedef __basic_future<_Res&> _Base_type; |
761 | ||
c910ceff | 762 | public: |
85db9dcc | 763 | constexpr shared_future() : _Base_type() { } |
b3eed6fe | 764 | |
c910ceff JW |
765 | /// Copy constructor |
766 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
767 | ||
b3eed6fe JW |
768 | /// Construct from a future rvalue |
769 | shared_future(future<_Res&>&& __uf) | |
c910ceff JW |
770 | : _Base_type(std::move(__uf)) |
771 | { } | |
772 | ||
b3eed6fe JW |
773 | /// Construct from a shared_future rvalue |
774 | shared_future(shared_future&& __sf) | |
775 | : _Base_type(std::move(__sf)) | |
776 | { } | |
777 | ||
778 | shared_future& operator=(const shared_future& __sf) | |
779 | { | |
780 | shared_future(__sf)._M_swap(*this); | |
781 | return *this; | |
782 | } | |
783 | ||
784 | shared_future& operator=(shared_future&& __sf) | |
785 | { | |
786 | shared_future(std::move(__sf))._M_swap(*this); | |
787 | return *this; | |
788 | } | |
c910ceff | 789 | |
c36abf03 BK |
790 | /// Retrieving the value |
791 | _Res& | |
b3eed6fe | 792 | get() { return this->_M_get_result()._M_get(); } |
c910ceff JW |
793 | }; |
794 | ||
c36abf03 | 795 | /// Explicit specialization for shared_future<void> |
c910ceff | 796 | template<> |
c36abf03 | 797 | class shared_future<void> : public __basic_future<void> |
c910ceff | 798 | { |
c36abf03 BK |
799 | typedef __basic_future<void> _Base_type; |
800 | ||
c910ceff | 801 | public: |
85db9dcc | 802 | constexpr shared_future() : _Base_type() { } |
b3eed6fe | 803 | |
c910ceff JW |
804 | /// Copy constructor |
805 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
806 | ||
b3eed6fe JW |
807 | /// Construct from a future rvalue |
808 | shared_future(future<void>&& __uf) | |
c910ceff JW |
809 | : _Base_type(std::move(__uf)) |
810 | { } | |
811 | ||
b3eed6fe JW |
812 | /// Construct from a shared_future rvalue |
813 | shared_future(shared_future&& __sf) | |
814 | : _Base_type(std::move(__sf)) | |
815 | { } | |
816 | ||
817 | shared_future& operator=(const shared_future& __sf) | |
818 | { | |
819 | shared_future(__sf)._M_swap(*this); | |
820 | return *this; | |
821 | } | |
822 | ||
823 | shared_future& operator=(shared_future&& __sf) | |
824 | { | |
825 | shared_future(std::move(__sf))._M_swap(*this); | |
826 | return *this; | |
827 | } | |
c910ceff | 828 | |
c36abf03 BK |
829 | // Retrieving the value |
830 | void | |
831 | get() { this->_M_get_result(); } | |
c910ceff JW |
832 | }; |
833 | ||
c36abf03 BK |
834 | // Now we can define the protected __basic_future constructors. |
835 | template<typename _Res> | |
19501406 PC |
836 | inline __basic_future<_Res>:: |
837 | __basic_future(const shared_future<_Res>& __sf) | |
c910ceff JW |
838 | : _M_state(__sf._M_state) |
839 | { } | |
840 | ||
c36abf03 | 841 | template<typename _Res> |
19501406 PC |
842 | inline __basic_future<_Res>:: |
843 | __basic_future(shared_future<_Res>&& __sf) | |
b3eed6fe JW |
844 | : _M_state(std::move(__sf._M_state)) |
845 | { } | |
846 | ||
847 | template<typename _Res> | |
19501406 PC |
848 | inline __basic_future<_Res>:: |
849 | __basic_future(future<_Res>&& __uf) | |
c910ceff JW |
850 | : _M_state(std::move(__uf._M_state)) |
851 | { } | |
852 | ||
e3e08a1d JW |
853 | template<typename _Res> |
854 | inline shared_future<_Res> | |
855 | future<_Res>::share() | |
856 | { return shared_future<_Res>(std::move(*this)); } | |
857 | ||
858 | template<typename _Res> | |
859 | inline shared_future<_Res&> | |
860 | future<_Res&>::share() | |
861 | { return shared_future<_Res&>(std::move(*this)); } | |
862 | ||
863 | inline shared_future<void> | |
864 | future<void>::share() | |
865 | { return shared_future<void>(std::move(*this)); } | |
c36abf03 BK |
866 | |
867 | /// Primary template for promise | |
868 | template<typename _Res> | |
c910ceff JW |
869 | class promise |
870 | { | |
e9599233 BK |
871 | typedef __future_base::_State_base _State; |
872 | typedef __future_base::_Result<_Res> _Res_type; | |
873 | typedef typename __future_base::_Ptr<_Res_type>::type _Ptr_type; | |
b3eed6fe | 874 | template<typename, typename> friend class _State::_Setter; |
c36abf03 BK |
875 | |
876 | shared_ptr<_State> _M_future; | |
b3eed6fe | 877 | _Ptr_type _M_storage; |
c36abf03 | 878 | |
c910ceff JW |
879 | public: |
880 | promise() | |
19501406 PC |
881 | : _M_future(std::make_shared<_State>()), |
882 | _M_storage(new _Res_type()) | |
c910ceff JW |
883 | { } |
884 | ||
885 | promise(promise&& __rhs) | |
886 | : _M_future(std::move(__rhs._M_future)), | |
19501406 | 887 | _M_storage(std::move(__rhs._M_storage)) |
c910ceff JW |
888 | { } |
889 | ||
c910ceff | 890 | template<typename _Allocator> |
b3eed6fe JW |
891 | promise(allocator_arg_t, const _Allocator& __a) |
892 | : _M_future(std::allocate_shared<_State>(__a)), | |
135a0d0a | 893 | _M_storage(__future_base::_S_allocate_result<_Res>(__a)) |
b3eed6fe | 894 | { } |
c910ceff JW |
895 | |
896 | promise(const promise&) = delete; | |
897 | ||
898 | ~promise() | |
899 | { | |
900 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
901 | _M_future->_M_break_promise(std::move(_M_storage)); | |
902 | } | |
903 | ||
c36abf03 | 904 | // Assignment |
c910ceff JW |
905 | promise& |
906 | operator=(promise&& __rhs) | |
907 | { | |
908 | promise(std::move(__rhs)).swap(*this); | |
909 | return *this; | |
910 | } | |
911 | ||
912 | promise& operator=(const promise&) = delete; | |
913 | ||
914 | void | |
915 | swap(promise& __rhs) | |
916 | { | |
917 | _M_future.swap(__rhs._M_future); | |
918 | _M_storage.swap(__rhs._M_storage); | |
919 | } | |
920 | ||
c36abf03 | 921 | // Retrieving the result |
b3eed6fe | 922 | future<_Res> |
c910ceff | 923 | get_future() |
b3eed6fe | 924 | { return future<_Res>(_M_future); } |
c910ceff | 925 | |
c36abf03 | 926 | // Setting the result |
c910ceff | 927 | void |
c36abf03 | 928 | set_value(const _Res& __r) |
c910ceff | 929 | { |
b3eed6fe JW |
930 | auto __setter = _State::__setter(this, __r); |
931 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff JW |
932 | } |
933 | ||
934 | void | |
c36abf03 | 935 | set_value(_Res&& __r) |
c910ceff | 936 | { |
b3eed6fe JW |
937 | auto __setter = _State::__setter(this, std::move(__r)); |
938 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff JW |
939 | } |
940 | ||
941 | void | |
942 | set_exception(exception_ptr __p) | |
943 | { | |
b3eed6fe JW |
944 | auto __setter = _State::__setter(__p, this); |
945 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff | 946 | } |
c910ceff JW |
947 | }; |
948 | ||
19501406 PC |
949 | template<typename _Res> |
950 | inline void | |
951 | swap(promise<_Res>& __x, promise<_Res>& __y) | |
952 | { __x.swap(__y); } | |
953 | ||
135a0d0a PC |
954 | template<typename _Res, typename _Alloc> |
955 | struct uses_allocator<promise<_Res>, _Alloc> | |
956 | : public true_type { }; | |
957 | ||
958 | ||
c36abf03 BK |
959 | /// Partial specialization for promise<R&> |
960 | template<typename _Res> | |
961 | class promise<_Res&> | |
c910ceff | 962 | { |
e9599233 BK |
963 | typedef __future_base::_State_base _State; |
964 | typedef __future_base::_Result<_Res&> _Res_type; | |
965 | typedef typename __future_base::_Ptr<_Res_type>::type _Ptr_type; | |
b3eed6fe | 966 | template<typename, typename> friend class _State::_Setter; |
c36abf03 BK |
967 | |
968 | shared_ptr<_State> _M_future; | |
b3eed6fe | 969 | _Ptr_type _M_storage; |
c36abf03 | 970 | |
c910ceff JW |
971 | public: |
972 | promise() | |
19501406 PC |
973 | : _M_future(std::make_shared<_State>()), |
974 | _M_storage(new _Res_type()) | |
c910ceff JW |
975 | { } |
976 | ||
977 | promise(promise&& __rhs) | |
c36abf03 BK |
978 | : _M_future(std::move(__rhs._M_future)), |
979 | _M_storage(std::move(__rhs._M_storage)) | |
c910ceff JW |
980 | { } |
981 | ||
c910ceff | 982 | template<typename _Allocator> |
b3eed6fe JW |
983 | promise(allocator_arg_t, const _Allocator& __a) |
984 | : _M_future(std::allocate_shared<_State>(__a)), | |
135a0d0a | 985 | _M_storage(__future_base::_S_allocate_result<_Res&>(__a)) |
b3eed6fe | 986 | { } |
c910ceff JW |
987 | |
988 | promise(const promise&) = delete; | |
989 | ||
990 | ~promise() | |
991 | { | |
992 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
993 | _M_future->_M_break_promise(std::move(_M_storage)); | |
994 | } | |
995 | ||
c36abf03 | 996 | // Assignment |
c910ceff JW |
997 | promise& |
998 | operator=(promise&& __rhs) | |
999 | { | |
1000 | promise(std::move(__rhs)).swap(*this); | |
1001 | return *this; | |
1002 | } | |
1003 | ||
1004 | promise& operator=(const promise&) = delete; | |
1005 | ||
1006 | void | |
1007 | swap(promise& __rhs) | |
1008 | { | |
1009 | _M_future.swap(__rhs._M_future); | |
1010 | _M_storage.swap(__rhs._M_storage); | |
1011 | } | |
1012 | ||
c36abf03 | 1013 | // Retrieving the result |
b3eed6fe | 1014 | future<_Res&> |
c910ceff | 1015 | get_future() |
b3eed6fe | 1016 | { return future<_Res&>(_M_future); } |
c910ceff | 1017 | |
c36abf03 | 1018 | // Setting the result |
c910ceff | 1019 | void |
c36abf03 | 1020 | set_value(_Res& __r) |
c910ceff | 1021 | { |
b3eed6fe JW |
1022 | auto __setter = _State::__setter(this, __r); |
1023 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff JW |
1024 | } |
1025 | ||
1026 | void | |
1027 | set_exception(exception_ptr __p) | |
1028 | { | |
b3eed6fe JW |
1029 | auto __setter = _State::__setter(__p, this); |
1030 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff | 1031 | } |
c910ceff JW |
1032 | }; |
1033 | ||
c36abf03 | 1034 | /// Explicit specialization for promise<void> |
c910ceff JW |
1035 | template<> |
1036 | class promise<void> | |
1037 | { | |
e9599233 BK |
1038 | typedef __future_base::_State_base _State; |
1039 | typedef __future_base::_Result<void> _Res_type; | |
1040 | typedef typename __future_base::_Ptr<_Res_type>::type _Ptr_type; | |
b3eed6fe | 1041 | template<typename, typename> friend class _State::_Setter; |
c36abf03 | 1042 | |
b3eed6fe JW |
1043 | shared_ptr<_State> _M_future; |
1044 | _Ptr_type _M_storage; | |
c36abf03 | 1045 | |
c910ceff JW |
1046 | public: |
1047 | promise() | |
c36abf03 | 1048 | : _M_future(std::make_shared<_State>()), |
b3eed6fe | 1049 | _M_storage(new _Res_type()) |
c910ceff JW |
1050 | { } |
1051 | ||
1052 | promise(promise&& __rhs) | |
1053 | : _M_future(std::move(__rhs._M_future)), | |
19501406 | 1054 | _M_storage(std::move(__rhs._M_storage)) |
c910ceff JW |
1055 | { } |
1056 | ||
c910ceff | 1057 | template<typename _Allocator> |
b3eed6fe JW |
1058 | promise(allocator_arg_t, const _Allocator& __a) |
1059 | : _M_future(std::allocate_shared<_State>(__a)), | |
135a0d0a | 1060 | _M_storage(__future_base::_S_allocate_result<void>(__a)) |
b3eed6fe | 1061 | { } |
c910ceff JW |
1062 | |
1063 | promise(const promise&) = delete; | |
1064 | ||
1065 | ~promise() | |
1066 | { | |
1067 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
1068 | _M_future->_M_break_promise(std::move(_M_storage)); | |
1069 | } | |
1070 | ||
c36abf03 | 1071 | // Assignment |
c910ceff JW |
1072 | promise& |
1073 | operator=(promise&& __rhs) | |
1074 | { | |
1075 | promise(std::move(__rhs)).swap(*this); | |
1076 | return *this; | |
1077 | } | |
1078 | ||
1079 | promise& operator=(const promise&) = delete; | |
1080 | ||
1081 | void | |
1082 | swap(promise& __rhs) | |
1083 | { | |
1084 | _M_future.swap(__rhs._M_future); | |
1085 | _M_storage.swap(__rhs._M_storage); | |
1086 | } | |
1087 | ||
c36abf03 | 1088 | // Retrieving the result |
b3eed6fe | 1089 | future<void> |
c910ceff | 1090 | get_future() |
b3eed6fe | 1091 | { return future<void>(_M_future); } |
c910ceff | 1092 | |
c36abf03 | 1093 | // Setting the result |
b3eed6fe JW |
1094 | void set_value(); |
1095 | ||
c910ceff | 1096 | void |
b3eed6fe | 1097 | set_exception(exception_ptr __p) |
c910ceff | 1098 | { |
b3eed6fe JW |
1099 | auto __setter = _State::__setter(__p, this); |
1100 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff | 1101 | } |
b3eed6fe | 1102 | }; |
c910ceff | 1103 | |
b3eed6fe JW |
1104 | // set void |
1105 | template<> | |
e9599233 | 1106 | struct __future_base::_State_base::_Setter<void, void> |
b3eed6fe JW |
1107 | { |
1108 | promise<void>::_Ptr_type operator()() | |
c910ceff | 1109 | { |
e9599233 | 1110 | _State_base::_S_check(_M_promise->_M_future); |
b3eed6fe | 1111 | return std::move(_M_promise->_M_storage); |
c910ceff JW |
1112 | } |
1113 | ||
b3eed6fe | 1114 | promise<void>* _M_promise; |
c910ceff JW |
1115 | }; |
1116 | ||
e9599233 BK |
1117 | inline __future_base::_State_base::_Setter<void, void> |
1118 | __future_base::_State_base::__setter(promise<void>* __prom) | |
b3eed6fe JW |
1119 | { |
1120 | return _Setter<void, void>{ __prom }; | |
1121 | } | |
1122 | ||
1123 | inline void | |
1124 | promise<void>::set_value() | |
1125 | { | |
1126 | auto __setter = _State::__setter(this); | |
1127 | _M_future->_M_set_result(std::move(__setter)); | |
1128 | } | |
1129 | ||
b3eed6fe JW |
1130 | |
1131 | template<typename _StateT, typename _Res> | |
1132 | struct __future_base::_Task_setter | |
c910ceff | 1133 | { |
b3eed6fe | 1134 | typename _StateT::_Ptr_type operator()() |
c910ceff | 1135 | { |
19501406 PC |
1136 | __try |
1137 | { | |
1138 | _M_state->_M_result->_M_set(_M_fn()); | |
1139 | } | |
1140 | __catch(...) | |
1141 | { | |
1142 | _M_state->_M_result->_M_error = current_exception(); | |
1143 | } | |
b3eed6fe | 1144 | return std::move(_M_state->_M_result); |
c910ceff | 1145 | } |
b3eed6fe JW |
1146 | _StateT* _M_state; |
1147 | std::function<_Res()> _M_fn; | |
c910ceff JW |
1148 | }; |
1149 | ||
b3eed6fe JW |
1150 | template<typename _StateT> |
1151 | struct __future_base::_Task_setter<_StateT, void> | |
c910ceff | 1152 | { |
b3eed6fe | 1153 | typename _StateT::_Ptr_type operator()() |
c910ceff | 1154 | { |
19501406 PC |
1155 | __try |
1156 | { | |
1157 | _M_fn(); | |
1158 | } | |
1159 | __catch(...) | |
1160 | { | |
1161 | _M_state->_M_result->_M_error = current_exception(); | |
1162 | } | |
1163 | return std::move(_M_state->_M_result); | |
c910ceff | 1164 | } |
b3eed6fe JW |
1165 | _StateT* _M_state; |
1166 | std::function<void()> _M_fn; | |
c910ceff JW |
1167 | }; |
1168 | ||
b3eed6fe | 1169 | template<typename _Res, typename... _Args> |
e9599233 BK |
1170 | struct __future_base::_Task_state<_Res(_Args...)> |
1171 | : __future_base::_State_base | |
b3eed6fe JW |
1172 | { |
1173 | typedef _Res _Res_type; | |
1174 | ||
1175 | _Task_state(std::function<_Res(_Args...)> __task) | |
1176 | : _M_result(new _Result<_Res>()), _M_task(std::move(__task)) | |
1177 | { } | |
1178 | ||
b3eed6fe JW |
1179 | template<typename _Func, typename _Alloc> |
1180 | _Task_state(_Func&& __task, const _Alloc& __a) | |
135a0d0a PC |
1181 | : _M_result(_S_allocate_result<_Res>(__a)), |
1182 | _M_task(allocator_arg, __a, std::move(__task)) | |
b3eed6fe | 1183 | { } |
b3eed6fe JW |
1184 | |
1185 | void | |
1186 | _M_run(_Args... __args) | |
1187 | { | |
1188 | // bound arguments decay so wrap lvalue references | |
1b3fad81 | 1189 | auto __bound = std::bind<_Res>(std::ref(_M_task), |
b3eed6fe JW |
1190 | _S_maybe_wrap_ref(std::forward<_Args>(__args))...); |
1191 | _Task_setter<_Task_state> __setter{ this, std::move(__bound) }; | |
1192 | _M_set_result(std::move(__setter)); | |
1193 | } | |
1194 | ||
1195 | template<typename, typename> friend class _Task_setter; | |
1196 | typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type; | |
1197 | _Ptr_type _M_result; | |
1198 | std::function<_Res(_Args...)> _M_task; | |
1199 | ||
1200 | template<typename _Tp> | |
1201 | static reference_wrapper<_Tp> | |
1202 | _S_maybe_wrap_ref(_Tp& __t) | |
1203 | { return std::ref(__t); } | |
1204 | ||
1205 | template<typename _Tp> | |
1206 | static typename enable_if<!is_lvalue_reference<_Tp>::value, | |
1207 | _Tp>::type&& | |
1208 | _S_maybe_wrap_ref(_Tp&& __t) | |
1209 | { return std::forward<_Tp>(__t); } | |
1210 | }; | |
c36abf03 | 1211 | |
3259554a | 1212 | /// packaged_task |
c36abf03 BK |
1213 | template<typename _Res, typename... _ArgTypes> |
1214 | class packaged_task<_Res(_ArgTypes...)> | |
c910ceff | 1215 | { |
b3eed6fe JW |
1216 | typedef __future_base::_Task_state<_Res(_ArgTypes...)> _State_type; |
1217 | shared_ptr<_State_type> _M_state; | |
c36abf03 | 1218 | |
c910ceff | 1219 | public: |
c36abf03 | 1220 | // Construction and destruction |
c910ceff JW |
1221 | packaged_task() { } |
1222 | ||
c910ceff JW |
1223 | template<typename _Fn> |
1224 | explicit | |
b3eed6fe | 1225 | packaged_task(_Fn&& __fn) |
e3e08a1d | 1226 | : _M_state(std::make_shared<_State_type>(std::forward<_Fn>(__fn))) |
b3eed6fe | 1227 | { } |
c910ceff | 1228 | |
c910ceff JW |
1229 | template<typename _Fn, typename _Allocator> |
1230 | explicit | |
e3e08a1d JW |
1231 | packaged_task(allocator_arg_t, const _Allocator& __a, _Fn&& __fn) |
1232 | : _M_state(std::allocate_shared<_State_type>(__a, | |
1233 | std::forward<_Fn>(__fn))) | |
c910ceff | 1234 | { } |
c910ceff | 1235 | |
b3eed6fe JW |
1236 | ~packaged_task() |
1237 | { | |
1238 | if (static_cast<bool>(_M_state) && !_M_state.unique()) | |
1239 | _M_state->_M_break_promise(std::move(_M_state->_M_result)); | |
1240 | } | |
c910ceff | 1241 | |
c36abf03 | 1242 | // No copy |
c910ceff JW |
1243 | packaged_task(packaged_task&) = delete; |
1244 | packaged_task& operator=(packaged_task&) = delete; | |
1245 | ||
c36abf03 | 1246 | // Move support |
c910ceff JW |
1247 | packaged_task(packaged_task&& __other) |
1248 | { this->swap(__other); } | |
1249 | ||
1250 | packaged_task& operator=(packaged_task&& __other) | |
1251 | { | |
1252 | packaged_task(std::move(__other)).swap(*this); | |
1253 | return *this; | |
1254 | } | |
1255 | ||
1256 | void | |
1257 | swap(packaged_task& __other) | |
b3eed6fe | 1258 | { _M_state.swap(__other._M_state); } |
c910ceff | 1259 | |
7a0269de JW |
1260 | bool |
1261 | valid() const | |
1262 | { return static_cast<bool>(_M_state); } | |
c910ceff | 1263 | |
c36abf03 | 1264 | // Result retrieval |
b3eed6fe | 1265 | future<_Res> |
c910ceff | 1266 | get_future() |
b3eed6fe | 1267 | { return future<_Res>(_M_state); } |
c910ceff | 1268 | |
c36abf03 | 1269 | // Execution |
c910ceff JW |
1270 | void |
1271 | operator()(_ArgTypes... __args) | |
1272 | { | |
e9599233 | 1273 | __future_base::_State_base::_S_check(_M_state); |
b3eed6fe JW |
1274 | _M_state->_M_run(std::forward<_ArgTypes>(__args)...); |
1275 | } | |
8d1b99e2 | 1276 | |
b3eed6fe JW |
1277 | void |
1278 | reset() | |
1279 | { | |
e9599233 | 1280 | __future_base::_State_base::_S_check(_M_state); |
b3eed6fe JW |
1281 | packaged_task(std::move(_M_state->_M_task)).swap(*this); |
1282 | } | |
1283 | }; | |
1284 | ||
94a86be0 | 1285 | /// swap |
19501406 | 1286 | template<typename _Res, typename... _ArgTypes> |
4e4d27aa | 1287 | inline void |
19501406 PC |
1288 | swap(packaged_task<_Res(_ArgTypes...)>& __x, |
1289 | packaged_task<_Res(_ArgTypes...)>& __y) | |
1290 | { __x.swap(__y); } | |
135a0d0a PC |
1291 | |
1292 | template<typename _Res, typename _Alloc> | |
1293 | struct uses_allocator<packaged_task<_Res>, _Alloc> | |
1294 | : public true_type { }; | |
1295 | ||
1296 | ||
b3eed6fe | 1297 | template<typename _Res> |
e9599233 | 1298 | class __future_base::_Deferred_state : public __future_base::_State_base |
b3eed6fe JW |
1299 | { |
1300 | public: | |
1301 | typedef _Res _Res_type; | |
1302 | ||
1303 | explicit | |
1304 | _Deferred_state(std::function<_Res()>&& __fn) | |
1305 | : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)) | |
1306 | { } | |
1307 | ||
1308 | private: | |
1309 | template<typename, typename> friend class _Task_setter; | |
1310 | typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type; | |
1311 | _Ptr_type _M_result; | |
1312 | std::function<_Res()> _M_fn; | |
1313 | ||
1314 | virtual void | |
1315 | _M_run_deferred() | |
1316 | { | |
1317 | _Task_setter<_Deferred_state> __setter{ this, _M_fn }; | |
1318 | // safe to call multiple times so ignore failure | |
1319 | _M_set_result(std::move(__setter), true); | |
1320 | } | |
1321 | }; | |
1322 | ||
1323 | template<typename _Res> | |
e9599233 | 1324 | class __future_base::_Async_state : public __future_base::_State_base |
b3eed6fe JW |
1325 | { |
1326 | public: | |
1327 | typedef _Res _Res_type; | |
1328 | ||
1329 | explicit | |
1330 | _Async_state(std::function<_Res()>&& __fn) | |
1331 | : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)), | |
19501406 | 1332 | _M_thread(mem_fn(&_Async_state::_M_do_run), this) |
b3eed6fe JW |
1333 | { } |
1334 | ||
1335 | ~_Async_state() { _M_thread.join(); } | |
1336 | ||
1337 | private: | |
1338 | void _M_do_run() | |
1339 | { | |
1340 | _Task_setter<_Async_state> __setter{ this, std::move(_M_fn) }; | |
1341 | _M_set_result(std::move(__setter)); | |
c910ceff JW |
1342 | } |
1343 | ||
b3eed6fe JW |
1344 | template<typename, typename> friend class _Task_setter; |
1345 | typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type; | |
1346 | _Ptr_type _M_result; | |
1347 | std::function<_Res()> _M_fn; | |
1348 | thread _M_thread; | |
c910ceff JW |
1349 | }; |
1350 | ||
94a86be0 | 1351 | /// async |
b3eed6fe | 1352 | template<typename _Fn, typename... _Args> |
73c5c5bb | 1353 | future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe JW |
1354 | async(launch __policy, _Fn&& __fn, _Args&&... __args) |
1355 | { | |
73c5c5bb | 1356 | typedef typename result_of<_Fn(_Args...)>::type result_type; |
e9599233 | 1357 | std::shared_ptr<__future_base::_State_base> __state; |
b3eed6fe | 1358 | if (__policy == launch::async) |
19501406 PC |
1359 | { |
1360 | typedef typename __future_base::_Async_state<result_type> _State; | |
1361 | __state = std::make_shared<_State>(std::bind<result_type>( | |
b3eed6fe | 1362 | std::forward<_Fn>(__fn), std::forward<_Args>(__args)...)); |
19501406 | 1363 | } |
b3eed6fe | 1364 | else |
19501406 PC |
1365 | { |
1366 | typedef typename __future_base::_Deferred_state<result_type> _State; | |
1367 | __state = std::make_shared<_State>(std::bind<result_type>( | |
b3eed6fe | 1368 | std::forward<_Fn>(__fn), std::forward<_Args>(__args)...)); |
19501406 | 1369 | } |
b3eed6fe JW |
1370 | return future<result_type>(__state); |
1371 | } | |
1372 | ||
94a86be0 | 1373 | /// async, potential overload |
b3eed6fe | 1374 | template<typename _Fn, typename... _Args> |
73c5c5bb JW |
1375 | inline typename |
1376 | enable_if<!is_same<typename decay<_Fn>::type, launch>::value, | |
1377 | future<decltype(std::declval<_Fn>()(std::declval<_Args>()...))> | |
1378 | >::type | |
b3eed6fe JW |
1379 | async(_Fn&& __fn, _Args&&... __args) |
1380 | { | |
1381 | return async(launch::any, std::forward<_Fn>(__fn), | |
19501406 | 1382 | std::forward<_Args>(__args)...); |
b3eed6fe JW |
1383 | } |
1384 | ||
c910ceff JW |
1385 | #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 |
1386 | // && _GLIBCXX_ATOMIC_BUILTINS_4 | |
1387 | ||
41ca4246 | 1388 | // @} group futures |
12ffa228 BK |
1389 | _GLIBCXX_END_NAMESPACE_VERSION |
1390 | } // namespace | |
41ca4246 | 1391 | |
c910ceff JW |
1392 | #endif // __GXX_EXPERIMENTAL_CXX0X__ |
1393 | ||
1394 | #endif // _GLIBCXX_FUTURE |