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