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