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