]>
Commit | Line | Data |
---|---|---|
c910ceff JW |
1 | // <future> -*- C++ -*- |
2 | ||
cbe34bb5 | 3 | // Copyright (C) 2009-2017 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 | ||
c910ceff | 38 | #include <mutex> |
b3eed6fe | 39 | #include <thread> |
c910ceff JW |
40 | #include <condition_variable> |
41 | #include <system_error> | |
afd88205 | 42 | #include <atomic> |
eae801ba | 43 | #include <bits/atomic_futex.h> |
abcd7e08 | 44 | #include <bits/functexcept.h> |
5579170b | 45 | #include <bits/invoke.h> |
6e48db73 JW |
46 | #include <bits/unique_ptr.h> |
47 | #include <bits/shared_ptr.h> | |
c05986b9 | 48 | #include <bits/std_function.h> |
6e48db73 | 49 | #include <bits/uses_allocator.h> |
b925bf59 | 50 | #include <bits/allocated_ptr.h> |
f2e2de5f | 51 | #include <ext/aligned_buffer.h> |
c910ceff | 52 | |
12ffa228 BK |
53 | namespace std _GLIBCXX_VISIBILITY(default) |
54 | { | |
55 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
53dc5044 | 56 | |
c910ceff JW |
57 | /** |
58 | * @defgroup futures Futures | |
59 | * @ingroup concurrency | |
60 | * | |
61 | * Classes for futures support. | |
62 | * @{ | |
63 | */ | |
64 | ||
65 | /// Error code for futures | |
66 | enum class future_errc | |
b3eed6fe | 67 | { |
7e98765e | 68 | future_already_retrieved = 1, |
b3eed6fe | 69 | promise_already_satisfied, |
7e98765e JW |
70 | no_state, |
71 | broken_promise | |
b3eed6fe | 72 | }; |
c910ceff | 73 | |
94a86be0 | 74 | /// Specialization. |
c910ceff JW |
75 | template<> |
76 | struct is_error_code_enum<future_errc> : public true_type { }; | |
77 | ||
78 | /// Points to a statically-allocated object derived from error_category. | |
94a86be0 | 79 | const error_category& |
84b63c01 | 80 | future_category() noexcept; |
c910ceff | 81 | |
94a86be0 | 82 | /// Overload for make_error_code. |
faa00511 | 83 | inline error_code |
84b63c01 | 84 | make_error_code(future_errc __errc) noexcept |
94a86be0 | 85 | { return error_code(static_cast<int>(__errc), future_category()); } |
c910ceff | 86 | |
94a86be0 | 87 | /// Overload for make_error_condition. |
faa00511 | 88 | inline error_condition |
84b63c01 | 89 | make_error_condition(future_errc __errc) noexcept |
94a86be0 | 90 | { return error_condition(static_cast<int>(__errc), future_category()); } |
c910ceff | 91 | |
8d1b99e2 BK |
92 | /** |
93 | * @brief Exception type thrown by futures. | |
94 | * @ingroup exceptions | |
95 | */ | |
c910ceff JW |
96 | class future_error : public logic_error |
97 | { | |
98 | public: | |
330cc73d JW |
99 | explicit |
100 | future_error(future_errc __errc) | |
101 | : future_error(std::make_error_code(__errc)) | |
c910ceff JW |
102 | { } |
103 | ||
84b63c01 | 104 | virtual ~future_error() noexcept; |
c910ceff | 105 | |
faa00511 | 106 | virtual const char* |
84b63c01 | 107 | what() const noexcept; |
c910ceff | 108 | |
faa00511 | 109 | const error_code& |
84b63c01 | 110 | code() const noexcept { return _M_code; } |
330cc73d | 111 | |
13908b44 | 112 | private: |
330cc73d JW |
113 | explicit |
114 | future_error(error_code __ec) | |
115 | : logic_error("std::future_error: " + __ec.message()), _M_code(__ec) | |
116 | { } | |
117 | ||
118 | friend void __throw_future_error(int); | |
119 | ||
120 | error_code _M_code; | |
c910ceff JW |
121 | }; |
122 | ||
3259554a | 123 | // Forward declarations. |
c36abf03 | 124 | template<typename _Res> |
b3eed6fe | 125 | class future; |
3259554a | 126 | |
c36abf03 | 127 | template<typename _Res> |
3259554a BK |
128 | class shared_future; |
129 | ||
faa00511 | 130 | template<typename _Signature> |
3259554a BK |
131 | class packaged_task; |
132 | ||
c36abf03 | 133 | template<typename _Res> |
3259554a BK |
134 | class promise; |
135 | ||
94a86be0 | 136 | /// Launch code for futures |
faa00511 JW |
137 | enum class launch |
138 | { | |
139 | async = 1, | |
140 | deferred = 2 | |
94a86be0 BK |
141 | }; |
142 | ||
a4eeb822 | 143 | constexpr launch operator&(launch __x, launch __y) |
faa00511 JW |
144 | { |
145 | return static_cast<launch>( | |
146 | static_cast<int>(__x) & static_cast<int>(__y)); | |
147 | } | |
148 | ||
a4eeb822 | 149 | constexpr launch operator|(launch __x, launch __y) |
faa00511 JW |
150 | { |
151 | return static_cast<launch>( | |
152 | static_cast<int>(__x) | static_cast<int>(__y)); | |
153 | } | |
154 | ||
a4eeb822 | 155 | constexpr launch operator^(launch __x, launch __y) |
faa00511 JW |
156 | { |
157 | return static_cast<launch>( | |
158 | static_cast<int>(__x) ^ static_cast<int>(__y)); | |
159 | } | |
160 | ||
a4eeb822 | 161 | constexpr launch operator~(launch __x) |
faa00511 JW |
162 | { return static_cast<launch>(~static_cast<int>(__x)); } |
163 | ||
164 | inline launch& operator&=(launch& __x, launch __y) | |
165 | { return __x = __x & __y; } | |
166 | ||
167 | inline launch& operator|=(launch& __x, launch __y) | |
168 | { return __x = __x | __y; } | |
169 | ||
170 | inline launch& operator^=(launch& __x, launch __y) | |
171 | { return __x = __x ^ __y; } | |
172 | ||
94a86be0 | 173 | /// Status code for futures |
faa00511 | 174 | enum class future_status |
94a86be0 BK |
175 | { |
176 | ready, | |
177 | timeout, | |
178 | deferred | |
179 | }; | |
b3eed6fe | 180 | |
75eb6443 JW |
181 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
182 | // 2021. Further incorrect usages of result_of | |
b3eed6fe | 183 | template<typename _Fn, typename... _Args> |
75eb6443 JW |
184 | using __async_result_of = typename result_of< |
185 | typename decay<_Fn>::type(typename decay<_Args>::type...)>::type; | |
186 | ||
187 | template<typename _Fn, typename... _Args> | |
188 | future<__async_result_of<_Fn, _Args...>> | |
b3eed6fe JW |
189 | async(launch __policy, _Fn&& __fn, _Args&&... __args); |
190 | ||
be7f7822 | 191 | template<typename _Fn, typename... _Args> |
75eb6443 | 192 | future<__async_result_of<_Fn, _Args...>> |
b3eed6fe JW |
193 | async(_Fn&& __fn, _Args&&... __args); |
194 | ||
41ca4246 | 195 | #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \ |
a152e96f | 196 | && (ATOMIC_INT_LOCK_FREE > 1) |
41ca4246 | 197 | |
c36abf03 BK |
198 | /// Base class and enclosing scope. |
199 | struct __future_base | |
c910ceff | 200 | { |
c36abf03 BK |
201 | /// Base class for results. |
202 | struct _Result_base | |
203 | { | |
204 | exception_ptr _M_error; | |
c910ceff | 205 | |
c36abf03 BK |
206 | _Result_base(const _Result_base&) = delete; |
207 | _Result_base& operator=(const _Result_base&) = delete; | |
c910ceff | 208 | |
b3eed6fe | 209 | // _M_destroy() allows derived classes to control deallocation |
c36abf03 | 210 | virtual void _M_destroy() = 0; |
c910ceff | 211 | |
c36abf03 BK |
212 | struct _Deleter |
213 | { | |
214 | void operator()(_Result_base* __fr) const { __fr->_M_destroy(); } | |
215 | }; | |
c910ceff | 216 | |
c36abf03 | 217 | protected: |
e9599233 BK |
218 | _Result_base(); |
219 | virtual ~_Result_base(); | |
c36abf03 | 220 | }; |
20f2653e | 221 | |
9db7c931 JW |
222 | /// A unique_ptr for result objects. |
223 | template<typename _Res> | |
224 | using _Ptr = unique_ptr<_Res, _Result_base::_Deleter>; | |
225 | ||
226 | /// A result object that has storage for an object of type _Res. | |
c36abf03 BK |
227 | template<typename _Res> |
228 | struct _Result : _Result_base | |
229 | { | |
230 | private: | |
f2e2de5f JW |
231 | __gnu_cxx::__aligned_buffer<_Res> _M_storage; |
232 | bool _M_initialized; | |
c36abf03 BK |
233 | |
234 | public: | |
aaad548e JW |
235 | typedef _Res result_type; |
236 | ||
84b63c01 | 237 | _Result() noexcept : _M_initialized() { } |
33ac58d5 | 238 | |
c36abf03 BK |
239 | ~_Result() |
240 | { | |
241 | if (_M_initialized) | |
242 | _M_value().~_Res(); | |
243 | } | |
244 | ||
245 | // Return lvalue, future will add const or rvalue-reference | |
faa00511 | 246 | _Res& |
f2e2de5f | 247 | _M_value() noexcept { return *_M_storage._M_ptr(); } |
c36abf03 BK |
248 | |
249 | void | |
250 | _M_set(const _Res& __res) | |
251 | { | |
f2e2de5f | 252 | ::new (_M_storage._M_addr()) _Res(__res); |
c36abf03 BK |
253 | _M_initialized = true; |
254 | } | |
255 | ||
256 | void | |
257 | _M_set(_Res&& __res) | |
258 | { | |
f2e2de5f | 259 | ::new (_M_storage._M_addr()) _Res(std::move(__res)); |
c36abf03 BK |
260 | _M_initialized = true; |
261 | } | |
262 | ||
263 | private: | |
264 | void _M_destroy() { delete this; } | |
c910ceff JW |
265 | }; |
266 | ||
9db7c931 | 267 | /// A result object that uses an allocator. |
b3eed6fe | 268 | template<typename _Res, typename _Alloc> |
a58a38b3 | 269 | struct _Result_alloc final : _Result<_Res>, _Alloc |
b3eed6fe | 270 | { |
b925bf59 | 271 | using __allocator_type = __alloc_rebind<_Alloc, _Result_alloc>; |
b3eed6fe JW |
272 | |
273 | explicit | |
0fd76d8e | 274 | _Result_alloc(const _Alloc& __a) : _Result<_Res>(), _Alloc(__a) |
b925bf59 | 275 | { } |
33ac58d5 | 276 | |
b3eed6fe JW |
277 | private: |
278 | void _M_destroy() | |
b925bf59 JW |
279 | { |
280 | __allocator_type __a(*this); | |
281 | __allocated_ptr<__allocator_type> __guard_ptr{ __a, this }; | |
282 | this->~_Result_alloc(); | |
283 | } | |
135a0d0a | 284 | }; |
b3eed6fe | 285 | |
9db7c931 | 286 | // Create a result object that uses an allocator. |
b3eed6fe | 287 | template<typename _Res, typename _Allocator> |
c4d9f419 | 288 | static _Ptr<_Result_alloc<_Res, _Allocator>> |
b3eed6fe JW |
289 | _S_allocate_result(const _Allocator& __a) |
290 | { | |
b925bf59 JW |
291 | using __result_type = _Result_alloc<_Res, _Allocator>; |
292 | typename __result_type::__allocator_type __a2(__a); | |
293 | auto __guard = std::__allocate_guarded(__a2); | |
294 | __result_type* __p = ::new((void*)__guard.get()) __result_type{__a}; | |
295 | __guard = nullptr; | |
296 | return _Ptr<__result_type>(__p); | |
b3eed6fe | 297 | } |
b3eed6fe | 298 | |
9db7c931 | 299 | // Keep it simple for std::allocator. |
aaad548e JW |
300 | template<typename _Res, typename _Tp> |
301 | static _Ptr<_Result<_Res>> | |
302 | _S_allocate_result(const std::allocator<_Tp>& __a) | |
303 | { | |
304 | return _Ptr<_Result<_Res>>(new _Result<_Res>); | |
305 | } | |
c910ceff | 306 | |
9db7c931 JW |
307 | // Base class for various types of shared state created by an |
308 | // asynchronous provider (such as a std::promise) and shared with one | |
309 | // or more associated futures. | |
f2f08be7 | 310 | class _State_baseV2 |
c910ceff | 311 | { |
c4d9f419 | 312 | typedef _Ptr<_Result_base> _Ptr_type; |
c910ceff | 313 | |
eae801ba TR |
314 | enum _Status : unsigned { |
315 | __not_ready, | |
316 | __ready | |
317 | }; | |
318 | ||
c36abf03 | 319 | _Ptr_type _M_result; |
eae801ba TR |
320 | __atomic_futex_unsigned<> _M_status; |
321 | atomic_flag _M_retrieved = ATOMIC_FLAG_INIT; | |
b3eed6fe | 322 | once_flag _M_once; |
c910ceff | 323 | |
c36abf03 | 324 | public: |
eae801ba TR |
325 | _State_baseV2() noexcept : _M_result(), _M_status(_Status::__not_ready) |
326 | { } | |
f2f08be7 JW |
327 | _State_baseV2(const _State_baseV2&) = delete; |
328 | _State_baseV2& operator=(const _State_baseV2&) = delete; | |
329 | virtual ~_State_baseV2() = default; | |
c910ceff | 330 | |
c36abf03 BK |
331 | _Result_base& |
332 | wait() | |
c910ceff | 333 | { |
9db7c931 | 334 | // Run any deferred function or join any asynchronous thread: |
f2f08be7 | 335 | _M_complete_async(); |
eae801ba TR |
336 | // Acquire MO makes sure this synchronizes with the thread that made |
337 | // the future ready. | |
338 | _M_status._M_load_when_equal(_Status::__ready, memory_order_acquire); | |
c36abf03 | 339 | return *_M_result; |
c910ceff | 340 | } |
c910ceff | 341 | |
c36abf03 | 342 | template<typename _Rep, typename _Period> |
488b3e65 | 343 | future_status |
c36abf03 BK |
344 | wait_for(const chrono::duration<_Rep, _Period>& __rel) |
345 | { | |
eae801ba TR |
346 | // First, check if the future has been made ready. Use acquire MO |
347 | // to synchronize with the thread that made it ready. | |
348 | if (_M_status._M_load(memory_order_acquire) == _Status::__ready) | |
488b3e65 | 349 | return future_status::ready; |
eae801ba | 350 | if (_M_is_deferred_future()) |
f2f08be7 | 351 | return future_status::deferred; |
eae801ba TR |
352 | if (_M_status._M_load_when_equal_for(_Status::__ready, |
353 | memory_order_acquire, __rel)) | |
f2f08be7 JW |
354 | { |
355 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
356 | // 2100. timed waiting functions must also join | |
9db7c931 JW |
357 | // This call is a no-op by default except on an async future, |
358 | // in which case the async thread is joined. It's also not a | |
359 | // no-op for a deferred future, but such a future will never | |
360 | // reach this point because it returns future_status::deferred | |
361 | // instead of waiting for the future to become ready (see | |
362 | // above). Async futures synchronize in this call, so we need | |
363 | // no further synchronization here. | |
f2f08be7 | 364 | _M_complete_async(); |
9db7c931 | 365 | |
f2f08be7 JW |
366 | return future_status::ready; |
367 | } | |
488b3e65 | 368 | return future_status::timeout; |
c36abf03 | 369 | } |
c910ceff | 370 | |
c36abf03 | 371 | template<typename _Clock, typename _Duration> |
488b3e65 | 372 | future_status |
c36abf03 BK |
373 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) |
374 | { | |
eae801ba TR |
375 | // First, check if the future has been made ready. Use acquire MO |
376 | // to synchronize with the thread that made it ready. | |
377 | if (_M_status._M_load(memory_order_acquire) == _Status::__ready) | |
488b3e65 | 378 | return future_status::ready; |
eae801ba | 379 | if (_M_is_deferred_future()) |
f2f08be7 | 380 | return future_status::deferred; |
eae801ba TR |
381 | if (_M_status._M_load_when_equal_until(_Status::__ready, |
382 | memory_order_acquire, __abs)) | |
f2f08be7 JW |
383 | { |
384 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
385 | // 2100. timed waiting functions must also join | |
9db7c931 | 386 | // See wait_for(...) above. |
f2f08be7 | 387 | _M_complete_async(); |
9db7c931 | 388 | |
f2f08be7 JW |
389 | return future_status::ready; |
390 | } | |
488b3e65 | 391 | return future_status::timeout; |
c36abf03 | 392 | } |
c910ceff | 393 | |
9db7c931 | 394 | // Provide a result to the shared state and make it ready. |
eae801ba | 395 | // Calls at most once: _M_result = __res(); |
c36abf03 | 396 | void |
b3eed6fe | 397 | _M_set_result(function<_Ptr_type()> __res, bool __ignore_failure = false) |
c910ceff | 398 | { |
eae801ba | 399 | bool __did_set = false; |
b3eed6fe JW |
400 | // all calls to this function are serialized, |
401 | // side-effects of invoking __res only happen once | |
a0eaa08c | 402 | call_once(_M_once, &_State_baseV2::_M_do_set, this, |
eae801ba TR |
403 | std::__addressof(__res), std::__addressof(__did_set)); |
404 | if (__did_set) | |
405 | // Use release MO to synchronize with observers of the ready state. | |
406 | _M_status._M_store_notify_all(_Status::__ready, | |
407 | memory_order_release); | |
a0eaa08c | 408 | else if (!__ignore_failure) |
b3eed6fe | 409 | __throw_future_error(int(future_errc::promise_already_satisfied)); |
c910ceff JW |
410 | } |
411 | ||
9db7c931 JW |
412 | // Provide a result to the shared state but delay making it ready |
413 | // until the calling thread exits. | |
eae801ba | 414 | // Calls at most once: _M_result = __res(); |
9db7c931 JW |
415 | void |
416 | _M_set_delayed_result(function<_Ptr_type()> __res, | |
417 | weak_ptr<_State_baseV2> __self) | |
418 | { | |
eae801ba | 419 | bool __did_set = false; |
9db7c931 | 420 | unique_ptr<_Make_ready> __mr{new _Make_ready}; |
9db7c931 JW |
421 | // all calls to this function are serialized, |
422 | // side-effects of invoking __res only happen once | |
423 | call_once(_M_once, &_State_baseV2::_M_do_set, this, | |
eae801ba TR |
424 | std::__addressof(__res), std::__addressof(__did_set)); |
425 | if (!__did_set) | |
9db7c931 JW |
426 | __throw_future_error(int(future_errc::promise_already_satisfied)); |
427 | __mr->_M_shared_state = std::move(__self); | |
428 | __mr->_M_set(); | |
429 | __mr.release(); | |
430 | } | |
431 | ||
432 | // Abandon this shared state. | |
c910ceff | 433 | void |
c36abf03 | 434 | _M_break_promise(_Ptr_type __res) |
c910ceff | 435 | { |
c36abf03 BK |
436 | if (static_cast<bool>(__res)) |
437 | { | |
330cc73d JW |
438 | __res->_M_error = |
439 | make_exception_ptr(future_error(future_errc::broken_promise)); | |
9db7c931 JW |
440 | // This function is only called when the last asynchronous result |
441 | // provider is abandoning this shared state, so noone can be | |
442 | // trying to make the shared state ready at the same time, and | |
443 | // we can access _M_result directly instead of through call_once. | |
eae801ba TR |
444 | _M_result.swap(__res); |
445 | // Use release MO to synchronize with observers of the ready state. | |
446 | _M_status._M_store_notify_all(_Status::__ready, | |
447 | memory_order_release); | |
c36abf03 | 448 | } |
c910ceff JW |
449 | } |
450 | ||
9db7c931 | 451 | // Called when this object is first passed to a future. |
c910ceff | 452 | void |
c36abf03 | 453 | _M_set_retrieved_flag() |
c910ceff | 454 | { |
c36abf03 BK |
455 | if (_M_retrieved.test_and_set()) |
456 | __throw_future_error(int(future_errc::future_already_retrieved)); | |
c910ceff JW |
457 | } |
458 | ||
b3eed6fe JW |
459 | template<typename _Res, typename _Arg> |
460 | struct _Setter; | |
461 | ||
462 | // set lvalues | |
463 | template<typename _Res, typename _Arg> | |
464 | struct _Setter<_Res, _Arg&> | |
465 | { | |
466 | // check this is only used by promise<R>::set_value(const R&) | |
4e48c109 | 467 | // or promise<R&>::set_value(R&) |
b3eed6fe | 468 | static_assert(is_same<_Res, _Arg&>::value // promise<R&> |
4e48c109 | 469 | || is_same<const _Res, _Arg>::value, // promise<R> |
b3eed6fe JW |
470 | "Invalid specialisation"); |
471 | ||
9db7c931 | 472 | // Used by std::promise to copy construct the result. |
9131b509 | 473 | typename promise<_Res>::_Ptr_type operator()() const |
b3eed6fe | 474 | { |
f2f08be7 | 475 | _State_baseV2::_S_check(_M_promise->_M_future); |
4e48c109 | 476 | _M_promise->_M_storage->_M_set(*_M_arg); |
b3eed6fe JW |
477 | return std::move(_M_promise->_M_storage); |
478 | } | |
479 | promise<_Res>* _M_promise; | |
4e48c109 | 480 | _Arg* _M_arg; |
b3eed6fe JW |
481 | }; |
482 | ||
483 | // set rvalues | |
484 | template<typename _Res> | |
485 | struct _Setter<_Res, _Res&&> | |
486 | { | |
9db7c931 | 487 | // Used by std::promise to move construct the result. |
9131b509 | 488 | typename promise<_Res>::_Ptr_type operator()() const |
b3eed6fe | 489 | { |
f2f08be7 | 490 | _State_baseV2::_S_check(_M_promise->_M_future); |
4e48c109 | 491 | _M_promise->_M_storage->_M_set(std::move(*_M_arg)); |
b3eed6fe JW |
492 | return std::move(_M_promise->_M_storage); |
493 | } | |
494 | promise<_Res>* _M_promise; | |
4e48c109 | 495 | _Res* _M_arg; |
b3eed6fe JW |
496 | }; |
497 | ||
498 | struct __exception_ptr_tag { }; | |
499 | ||
500 | // set exceptions | |
501 | template<typename _Res> | |
502 | struct _Setter<_Res, __exception_ptr_tag> | |
503 | { | |
9db7c931 | 504 | // Used by std::promise to store an exception as the result. |
9131b509 | 505 | typename promise<_Res>::_Ptr_type operator()() const |
b3eed6fe | 506 | { |
f2f08be7 | 507 | _State_baseV2::_S_check(_M_promise->_M_future); |
4e48c109 | 508 | _M_promise->_M_storage->_M_error = *_M_ex; |
b3eed6fe JW |
509 | return std::move(_M_promise->_M_storage); |
510 | } | |
511 | ||
512 | promise<_Res>* _M_promise; | |
4e48c109 | 513 | exception_ptr* _M_ex; |
b3eed6fe JW |
514 | }; |
515 | ||
516 | template<typename _Res, typename _Arg> | |
517 | static _Setter<_Res, _Arg&&> | |
518 | __setter(promise<_Res>* __prom, _Arg&& __arg) | |
519 | { | |
f885fa89 | 520 | return _Setter<_Res, _Arg&&>{ __prom, std::__addressof(__arg) }; |
b3eed6fe JW |
521 | } |
522 | ||
523 | template<typename _Res> | |
524 | static _Setter<_Res, __exception_ptr_tag> | |
525 | __setter(exception_ptr& __ex, promise<_Res>* __prom) | |
526 | { | |
4e48c109 | 527 | return _Setter<_Res, __exception_ptr_tag>{ __prom, &__ex }; |
b3eed6fe JW |
528 | } |
529 | ||
b3eed6fe | 530 | template<typename _Tp> |
c93fa3ca | 531 | static void |
b3eed6fe JW |
532 | _S_check(const shared_ptr<_Tp>& __p) |
533 | { | |
534 | if (!static_cast<bool>(__p)) | |
535 | __throw_future_error((int)future_errc::no_state); | |
536 | } | |
537 | ||
c910ceff | 538 | private: |
9db7c931 | 539 | // The function invoked with std::call_once(_M_once, ...). |
b3eed6fe | 540 | void |
eae801ba | 541 | _M_do_set(function<_Ptr_type()>* __f, bool* __did_set) |
c36abf03 | 542 | { |
eae801ba TR |
543 | _Ptr_type __res = (*__f)(); |
544 | // Notify the caller that we did try to set; if we do not throw an | |
545 | // exception, the caller will be aware that it did set (e.g., see | |
546 | // _M_set_result). | |
547 | *__did_set = true; | |
548 | _M_result.swap(__res); // nothrow | |
c36abf03 | 549 | } |
c910ceff | 550 | |
f2f08be7 JW |
551 | // Wait for completion of async function. |
552 | virtual void _M_complete_async() { } | |
553 | ||
9db7c931 | 554 | // Return true if state corresponds to a deferred function. |
eae801ba | 555 | virtual bool _M_is_deferred_future() const { return false; } |
9db7c931 JW |
556 | |
557 | struct _Make_ready final : __at_thread_exit_elt | |
558 | { | |
559 | weak_ptr<_State_baseV2> _M_shared_state; | |
560 | static void _S_run(void*); | |
561 | void _M_set(); | |
562 | }; | |
c910ceff | 563 | }; |
b3eed6fe | 564 | |
f2f08be7 JW |
565 | #ifdef _GLIBCXX_ASYNC_ABI_COMPAT |
566 | class _State_base; | |
567 | class _Async_state_common; | |
568 | #else | |
569 | using _State_base = _State_baseV2; | |
570 | class _Async_state_commonV2; | |
571 | #endif | |
572 | ||
a2284544 JW |
573 | template<typename _BoundFn, |
574 | typename _Res = decltype(std::declval<_BoundFn&>()())> | |
b3eed6fe JW |
575 | class _Deferred_state; |
576 | ||
a2284544 JW |
577 | template<typename _BoundFn, |
578 | typename _Res = decltype(std::declval<_BoundFn&>()())> | |
488b3e65 | 579 | class _Async_state_impl; |
b3eed6fe JW |
580 | |
581 | template<typename _Signature> | |
aaad548e JW |
582 | class _Task_state_base; |
583 | ||
584 | template<typename _Fn, typename _Alloc, typename _Signature> | |
b3eed6fe JW |
585 | class _Task_state; |
586 | ||
4880236e JW |
587 | template<typename _BoundFn> |
588 | static std::shared_ptr<_State_base> | |
589 | _S_make_deferred_state(_BoundFn&& __fn); | |
590 | ||
591 | template<typename _BoundFn> | |
592 | static std::shared_ptr<_State_base> | |
593 | _S_make_async_state(_BoundFn&& __fn); | |
594 | ||
4e48c109 | 595 | template<typename _Res_ptr, typename _Fn, |
aaad548e | 596 | typename _Res = typename _Res_ptr::element_type::result_type> |
b3eed6fe | 597 | struct _Task_setter; |
4880236e JW |
598 | |
599 | template<typename _Res_ptr, typename _BoundFn> | |
4e48c109 JW |
600 | static _Task_setter<_Res_ptr, _BoundFn> |
601 | _S_task_setter(_Res_ptr& __ptr, _BoundFn& __call) | |
4880236e | 602 | { |
4e48c109 | 603 | return { std::__addressof(__ptr), std::__addressof(__call) }; |
4880236e | 604 | } |
c36abf03 | 605 | }; |
c910ceff | 606 | |
c36abf03 BK |
607 | /// Partial specialization for reference types. |
608 | template<typename _Res> | |
609 | struct __future_base::_Result<_Res&> : __future_base::_Result_base | |
610 | { | |
aaad548e JW |
611 | typedef _Res& result_type; |
612 | ||
84b63c01 | 613 | _Result() noexcept : _M_value_ptr() { } |
c910ceff | 614 | |
9db7c931 JW |
615 | void |
616 | _M_set(_Res& __res) noexcept | |
617 | { _M_value_ptr = std::addressof(__res); } | |
b3eed6fe | 618 | |
84b63c01 | 619 | _Res& _M_get() noexcept { return *_M_value_ptr; } |
b3eed6fe JW |
620 | |
621 | private: | |
c36abf03 | 622 | _Res* _M_value_ptr; |
faa00511 | 623 | |
c910ceff JW |
624 | void _M_destroy() { delete this; } |
625 | }; | |
626 | ||
c36abf03 | 627 | /// Explicit specialization for void. |
c910ceff | 628 | template<> |
c36abf03 | 629 | struct __future_base::_Result<void> : __future_base::_Result_base |
c910ceff | 630 | { |
aaad548e JW |
631 | typedef void result_type; |
632 | ||
c36abf03 | 633 | private: |
c910ceff JW |
634 | void _M_destroy() { delete this; } |
635 | }; | |
636 | ||
db0b7db3 JW |
637 | #ifndef _GLIBCXX_ASYNC_ABI_COMPAT |
638 | ||
4e48c109 JW |
639 | // Allow _Setter objects to be stored locally in std::function |
640 | template<typename _Res, typename _Arg> | |
641 | struct __is_location_invariant | |
642 | <__future_base::_State_base::_Setter<_Res, _Arg>> | |
643 | : true_type { }; | |
644 | ||
645 | // Allow _Task_setter objects to be stored locally in std::function | |
646 | template<typename _Res_ptr, typename _Fn, typename _Res> | |
647 | struct __is_location_invariant | |
648 | <__future_base::_Task_setter<_Res_ptr, _Fn, _Res>> | |
649 | : true_type { }; | |
650 | ||
b3eed6fe | 651 | /// Common implementation for future and shared_future. |
c36abf03 BK |
652 | template<typename _Res> |
653 | class __basic_future : public __future_base | |
c910ceff | 654 | { |
c36abf03 | 655 | protected: |
e9599233 | 656 | typedef shared_ptr<_State_base> __state_type; |
c36abf03 BK |
657 | typedef __future_base::_Result<_Res>& __result_type; |
658 | ||
659 | private: | |
660 | __state_type _M_state; | |
661 | ||
c910ceff | 662 | public: |
c36abf03 BK |
663 | // Disable copying. |
664 | __basic_future(const __basic_future&) = delete; | |
665 | __basic_future& operator=(const __basic_future&) = delete; | |
c910ceff | 666 | |
faa00511 | 667 | bool |
84b63c01 | 668 | valid() const noexcept { return static_cast<bool>(_M_state); } |
c910ceff | 669 | |
faa00511 | 670 | void |
5262c72a JW |
671 | wait() const |
672 | { | |
e9599233 | 673 | _State_base::_S_check(_M_state); |
5262c72a JW |
674 | _M_state->wait(); |
675 | } | |
c910ceff JW |
676 | |
677 | template<typename _Rep, typename _Period> | |
488b3e65 | 678 | future_status |
c910ceff | 679 | wait_for(const chrono::duration<_Rep, _Period>& __rel) const |
5262c72a | 680 | { |
e9599233 | 681 | _State_base::_S_check(_M_state); |
5262c72a JW |
682 | return _M_state->wait_for(__rel); |
683 | } | |
c910ceff JW |
684 | |
685 | template<typename _Clock, typename _Duration> | |
488b3e65 | 686 | future_status |
c910ceff | 687 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) const |
5262c72a | 688 | { |
e9599233 | 689 | _State_base::_S_check(_M_state); |
5262c72a JW |
690 | return _M_state->wait_until(__abs); |
691 | } | |
c910ceff JW |
692 | |
693 | protected: | |
c36abf03 BK |
694 | /// Wait for the state to be ready and rethrow any stored exception |
695 | __result_type | |
c93fa3ca | 696 | _M_get_result() const |
c910ceff | 697 | { |
e9599233 | 698 | _State_base::_S_check(_M_state); |
b3eed6fe | 699 | _Result_base& __res = _M_state->wait(); |
c910ceff JW |
700 | if (!(__res._M_error == 0)) |
701 | rethrow_exception(__res._M_error); | |
c36abf03 | 702 | return static_cast<__result_type>(__res); |
c910ceff JW |
703 | } |
704 | ||
84b63c01 | 705 | void _M_swap(__basic_future& __that) noexcept |
b3eed6fe JW |
706 | { |
707 | _M_state.swap(__that._M_state); | |
708 | } | |
709 | ||
710 | // Construction of a future by promise::get_future() | |
c910ceff | 711 | explicit |
c36abf03 | 712 | __basic_future(const __state_type& __state) : _M_state(__state) |
c910ceff | 713 | { |
e9599233 | 714 | _State_base::_S_check(_M_state); |
b3eed6fe | 715 | _M_state->_M_set_retrieved_flag(); |
c910ceff JW |
716 | } |
717 | ||
c36abf03 | 718 | // Copy construction from a shared_future |
c910ceff | 719 | explicit |
84b63c01 | 720 | __basic_future(const shared_future<_Res>&) noexcept; |
c910ceff | 721 | |
b3eed6fe | 722 | // Move construction from a shared_future |
c910ceff | 723 | explicit |
84b63c01 | 724 | __basic_future(shared_future<_Res>&&) noexcept; |
b3eed6fe JW |
725 | |
726 | // Move construction from a future | |
727 | explicit | |
84b63c01 | 728 | __basic_future(future<_Res>&&) noexcept; |
b3eed6fe | 729 | |
84b63c01 | 730 | constexpr __basic_future() noexcept : _M_state() { } |
b3eed6fe JW |
731 | |
732 | struct _Reset | |
733 | { | |
84b63c01 | 734 | explicit _Reset(__basic_future& __fut) noexcept : _M_fut(__fut) { } |
b3eed6fe JW |
735 | ~_Reset() { _M_fut._M_state.reset(); } |
736 | __basic_future& _M_fut; | |
737 | }; | |
c910ceff JW |
738 | }; |
739 | ||
c36abf03 | 740 | |
b3eed6fe | 741 | /// Primary template for future. |
c36abf03 | 742 | template<typename _Res> |
b3eed6fe | 743 | class future : public __basic_future<_Res> |
c910ceff | 744 | { |
c36abf03 | 745 | friend class promise<_Res>; |
b3eed6fe JW |
746 | template<typename> friend class packaged_task; |
747 | template<typename _Fn, typename... _Args> | |
75eb6443 | 748 | friend future<__async_result_of<_Fn, _Args...>> |
b3eed6fe | 749 | async(launch, _Fn&&, _Args&&...); |
c36abf03 BK |
750 | |
751 | typedef __basic_future<_Res> _Base_type; | |
752 | typedef typename _Base_type::__state_type __state_type; | |
c36abf03 BK |
753 | |
754 | explicit | |
b3eed6fe | 755 | future(const __state_type& __state) : _Base_type(__state) { } |
c910ceff JW |
756 | |
757 | public: | |
84b63c01 | 758 | constexpr future() noexcept : _Base_type() { } |
b3eed6fe | 759 | |
c910ceff | 760 | /// Move constructor |
84b63c01 | 761 | future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } |
c910ceff | 762 | |
c36abf03 | 763 | // Disable copying |
b3eed6fe JW |
764 | future(const future&) = delete; |
765 | future& operator=(const future&) = delete; | |
766 | ||
84b63c01 | 767 | future& operator=(future&& __fut) noexcept |
b3eed6fe JW |
768 | { |
769 | future(std::move(__fut))._M_swap(*this); | |
770 | return *this; | |
771 | } | |
c910ceff | 772 | |
c36abf03 | 773 | /// Retrieving the value |
b3eed6fe | 774 | _Res |
c910ceff | 775 | get() |
b3eed6fe JW |
776 | { |
777 | typename _Base_type::_Reset __reset(*this); | |
778 | return std::move(this->_M_get_result()._M_value()); | |
779 | } | |
e3e08a1d | 780 | |
9c52cc01 | 781 | shared_future<_Res> share() noexcept; |
c910ceff | 782 | }; |
faa00511 | 783 | |
b3eed6fe | 784 | /// Partial specialization for future<R&> |
c36abf03 | 785 | template<typename _Res> |
b3eed6fe | 786 | class future<_Res&> : public __basic_future<_Res&> |
c910ceff | 787 | { |
c36abf03 | 788 | friend class promise<_Res&>; |
b3eed6fe JW |
789 | template<typename> friend class packaged_task; |
790 | template<typename _Fn, typename... _Args> | |
75eb6443 | 791 | friend future<__async_result_of<_Fn, _Args...>> |
b3eed6fe | 792 | async(launch, _Fn&&, _Args&&...); |
c36abf03 BK |
793 | |
794 | typedef __basic_future<_Res&> _Base_type; | |
795 | typedef typename _Base_type::__state_type __state_type; | |
796 | ||
797 | explicit | |
b3eed6fe | 798 | future(const __state_type& __state) : _Base_type(__state) { } |
c36abf03 | 799 | |
c910ceff | 800 | public: |
84b63c01 | 801 | constexpr future() noexcept : _Base_type() { } |
b3eed6fe | 802 | |
c910ceff | 803 | /// Move constructor |
84b63c01 | 804 | future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } |
c910ceff | 805 | |
c36abf03 | 806 | // Disable copying |
b3eed6fe JW |
807 | future(const future&) = delete; |
808 | future& operator=(const future&) = delete; | |
809 | ||
84b63c01 | 810 | future& operator=(future&& __fut) noexcept |
b3eed6fe JW |
811 | { |
812 | future(std::move(__fut))._M_swap(*this); | |
813 | return *this; | |
814 | } | |
c910ceff | 815 | |
c36abf03 | 816 | /// Retrieving the value |
faa00511 | 817 | _Res& |
b3eed6fe JW |
818 | get() |
819 | { | |
820 | typename _Base_type::_Reset __reset(*this); | |
821 | return this->_M_get_result()._M_get(); | |
822 | } | |
e3e08a1d | 823 | |
9c52cc01 | 824 | shared_future<_Res&> share() noexcept; |
c36abf03 | 825 | }; |
c910ceff | 826 | |
b3eed6fe | 827 | /// Explicit specialization for future<void> |
c36abf03 | 828 | template<> |
b3eed6fe | 829 | class future<void> : public __basic_future<void> |
c36abf03 BK |
830 | { |
831 | friend class promise<void>; | |
b3eed6fe JW |
832 | template<typename> friend class packaged_task; |
833 | template<typename _Fn, typename... _Args> | |
75eb6443 | 834 | friend future<__async_result_of<_Fn, _Args...>> |
b3eed6fe | 835 | async(launch, _Fn&&, _Args&&...); |
c910ceff | 836 | |
c36abf03 BK |
837 | typedef __basic_future<void> _Base_type; |
838 | typedef typename _Base_type::__state_type __state_type; | |
c910ceff JW |
839 | |
840 | explicit | |
b3eed6fe | 841 | future(const __state_type& __state) : _Base_type(__state) { } |
c910ceff | 842 | |
c910ceff | 843 | public: |
84b63c01 | 844 | constexpr future() noexcept : _Base_type() { } |
b3eed6fe | 845 | |
c910ceff | 846 | /// Move constructor |
84b63c01 | 847 | future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { } |
c910ceff | 848 | |
c36abf03 | 849 | // Disable copying |
b3eed6fe JW |
850 | future(const future&) = delete; |
851 | future& operator=(const future&) = delete; | |
852 | ||
84b63c01 | 853 | future& operator=(future&& __fut) noexcept |
b3eed6fe JW |
854 | { |
855 | future(std::move(__fut))._M_swap(*this); | |
856 | return *this; | |
857 | } | |
c910ceff | 858 | |
c36abf03 | 859 | /// Retrieving the value |
faa00511 | 860 | void |
b3eed6fe JW |
861 | get() |
862 | { | |
863 | typename _Base_type::_Reset __reset(*this); | |
864 | this->_M_get_result(); | |
865 | } | |
e3e08a1d | 866 | |
9c52cc01 | 867 | shared_future<void> share() noexcept; |
c910ceff JW |
868 | }; |
869 | ||
c36abf03 BK |
870 | |
871 | /// Primary template for shared_future. | |
872 | template<typename _Res> | |
873 | class shared_future : public __basic_future<_Res> | |
c910ceff | 874 | { |
c36abf03 BK |
875 | typedef __basic_future<_Res> _Base_type; |
876 | ||
c910ceff | 877 | public: |
84b63c01 | 878 | constexpr shared_future() noexcept : _Base_type() { } |
b3eed6fe | 879 | |
c910ceff JW |
880 | /// Copy constructor |
881 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
882 | ||
b3eed6fe | 883 | /// Construct from a future rvalue |
84b63c01 | 884 | shared_future(future<_Res>&& __uf) noexcept |
c910ceff JW |
885 | : _Base_type(std::move(__uf)) |
886 | { } | |
887 | ||
b3eed6fe | 888 | /// Construct from a shared_future rvalue |
84b63c01 | 889 | shared_future(shared_future&& __sf) noexcept |
b3eed6fe JW |
890 | : _Base_type(std::move(__sf)) |
891 | { } | |
892 | ||
893 | shared_future& operator=(const shared_future& __sf) | |
894 | { | |
895 | shared_future(__sf)._M_swap(*this); | |
896 | return *this; | |
897 | } | |
898 | ||
84b63c01 | 899 | shared_future& operator=(shared_future&& __sf) noexcept |
b3eed6fe JW |
900 | { |
901 | shared_future(std::move(__sf))._M_swap(*this); | |
902 | return *this; | |
903 | } | |
c910ceff | 904 | |
c36abf03 BK |
905 | /// Retrieving the value |
906 | const _Res& | |
c93fa3ca | 907 | get() const { return this->_M_get_result()._M_value(); } |
c910ceff | 908 | }; |
faa00511 | 909 | |
c36abf03 BK |
910 | /// Partial specialization for shared_future<R&> |
911 | template<typename _Res> | |
912 | class shared_future<_Res&> : public __basic_future<_Res&> | |
c910ceff | 913 | { |
c36abf03 BK |
914 | typedef __basic_future<_Res&> _Base_type; |
915 | ||
c910ceff | 916 | public: |
84b63c01 | 917 | constexpr shared_future() noexcept : _Base_type() { } |
b3eed6fe | 918 | |
c910ceff JW |
919 | /// Copy constructor |
920 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
921 | ||
b3eed6fe | 922 | /// Construct from a future rvalue |
84b63c01 | 923 | shared_future(future<_Res&>&& __uf) noexcept |
c910ceff JW |
924 | : _Base_type(std::move(__uf)) |
925 | { } | |
926 | ||
b3eed6fe | 927 | /// Construct from a shared_future rvalue |
84b63c01 | 928 | shared_future(shared_future&& __sf) noexcept |
b3eed6fe JW |
929 | : _Base_type(std::move(__sf)) |
930 | { } | |
931 | ||
932 | shared_future& operator=(const shared_future& __sf) | |
933 | { | |
934 | shared_future(__sf)._M_swap(*this); | |
935 | return *this; | |
936 | } | |
937 | ||
84b63c01 | 938 | shared_future& operator=(shared_future&& __sf) noexcept |
b3eed6fe JW |
939 | { |
940 | shared_future(std::move(__sf))._M_swap(*this); | |
941 | return *this; | |
942 | } | |
c910ceff | 943 | |
c36abf03 | 944 | /// Retrieving the value |
faa00511 | 945 | _Res& |
c93fa3ca | 946 | get() const { return this->_M_get_result()._M_get(); } |
c910ceff JW |
947 | }; |
948 | ||
c36abf03 | 949 | /// Explicit specialization for shared_future<void> |
c910ceff | 950 | template<> |
c36abf03 | 951 | class shared_future<void> : public __basic_future<void> |
c910ceff | 952 | { |
c36abf03 BK |
953 | typedef __basic_future<void> _Base_type; |
954 | ||
c910ceff | 955 | public: |
84b63c01 | 956 | constexpr shared_future() noexcept : _Base_type() { } |
b3eed6fe | 957 | |
c910ceff JW |
958 | /// Copy constructor |
959 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
960 | ||
b3eed6fe | 961 | /// Construct from a future rvalue |
84b63c01 | 962 | shared_future(future<void>&& __uf) noexcept |
c910ceff JW |
963 | : _Base_type(std::move(__uf)) |
964 | { } | |
965 | ||
b3eed6fe | 966 | /// Construct from a shared_future rvalue |
84b63c01 | 967 | shared_future(shared_future&& __sf) noexcept |
b3eed6fe JW |
968 | : _Base_type(std::move(__sf)) |
969 | { } | |
970 | ||
971 | shared_future& operator=(const shared_future& __sf) | |
972 | { | |
973 | shared_future(__sf)._M_swap(*this); | |
974 | return *this; | |
975 | } | |
976 | ||
84b63c01 | 977 | shared_future& operator=(shared_future&& __sf) noexcept |
b3eed6fe JW |
978 | { |
979 | shared_future(std::move(__sf))._M_swap(*this); | |
980 | return *this; | |
981 | } | |
c910ceff | 982 | |
c36abf03 | 983 | // Retrieving the value |
faa00511 | 984 | void |
c93fa3ca | 985 | get() const { this->_M_get_result(); } |
c910ceff JW |
986 | }; |
987 | ||
c36abf03 BK |
988 | // Now we can define the protected __basic_future constructors. |
989 | template<typename _Res> | |
19501406 | 990 | inline __basic_future<_Res>:: |
84b63c01 | 991 | __basic_future(const shared_future<_Res>& __sf) noexcept |
c910ceff JW |
992 | : _M_state(__sf._M_state) |
993 | { } | |
994 | ||
c36abf03 | 995 | template<typename _Res> |
19501406 | 996 | inline __basic_future<_Res>:: |
84b63c01 | 997 | __basic_future(shared_future<_Res>&& __sf) noexcept |
b3eed6fe JW |
998 | : _M_state(std::move(__sf._M_state)) |
999 | { } | |
1000 | ||
1001 | template<typename _Res> | |
19501406 | 1002 | inline __basic_future<_Res>:: |
84b63c01 | 1003 | __basic_future(future<_Res>&& __uf) noexcept |
c910ceff JW |
1004 | : _M_state(std::move(__uf._M_state)) |
1005 | { } | |
1006 | ||
9c52cc01 JW |
1007 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1008 | // 2556. Wide contract for future::share() | |
e3e08a1d JW |
1009 | template<typename _Res> |
1010 | inline shared_future<_Res> | |
9c52cc01 | 1011 | future<_Res>::share() noexcept |
e3e08a1d JW |
1012 | { return shared_future<_Res>(std::move(*this)); } |
1013 | ||
1014 | template<typename _Res> | |
1015 | inline shared_future<_Res&> | |
9c52cc01 | 1016 | future<_Res&>::share() noexcept |
e3e08a1d JW |
1017 | { return shared_future<_Res&>(std::move(*this)); } |
1018 | ||
1019 | inline shared_future<void> | |
9c52cc01 | 1020 | future<void>::share() noexcept |
e3e08a1d | 1021 | { return shared_future<void>(std::move(*this)); } |
c36abf03 BK |
1022 | |
1023 | /// Primary template for promise | |
1024 | template<typename _Res> | |
c910ceff JW |
1025 | class promise |
1026 | { | |
c4d9f419 JW |
1027 | typedef __future_base::_State_base _State; |
1028 | typedef __future_base::_Result<_Res> _Res_type; | |
1029 | typedef __future_base::_Ptr<_Res_type> _Ptr_type; | |
b3eed6fe | 1030 | template<typename, typename> friend class _State::_Setter; |
faa00511 | 1031 | |
c36abf03 | 1032 | shared_ptr<_State> _M_future; |
b3eed6fe | 1033 | _Ptr_type _M_storage; |
c36abf03 | 1034 | |
c910ceff JW |
1035 | public: |
1036 | promise() | |
19501406 PC |
1037 | : _M_future(std::make_shared<_State>()), |
1038 | _M_storage(new _Res_type()) | |
c910ceff JW |
1039 | { } |
1040 | ||
84b63c01 | 1041 | promise(promise&& __rhs) noexcept |
c910ceff | 1042 | : _M_future(std::move(__rhs._M_future)), |
19501406 | 1043 | _M_storage(std::move(__rhs._M_storage)) |
c910ceff JW |
1044 | { } |
1045 | ||
c910ceff | 1046 | template<typename _Allocator> |
b3eed6fe JW |
1047 | promise(allocator_arg_t, const _Allocator& __a) |
1048 | : _M_future(std::allocate_shared<_State>(__a)), | |
135a0d0a | 1049 | _M_storage(__future_base::_S_allocate_result<_Res>(__a)) |
b3eed6fe | 1050 | { } |
c910ceff | 1051 | |
376d7c51 JW |
1052 | template<typename _Allocator> |
1053 | promise(allocator_arg_t, const _Allocator&, promise&& __rhs) | |
1054 | : _M_future(std::move(__rhs._M_future)), | |
1055 | _M_storage(std::move(__rhs._M_storage)) | |
1056 | { } | |
1057 | ||
c910ceff JW |
1058 | promise(const promise&) = delete; |
1059 | ||
1060 | ~promise() | |
1061 | { | |
1062 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
1063 | _M_future->_M_break_promise(std::move(_M_storage)); | |
1064 | } | |
1065 | ||
c36abf03 | 1066 | // Assignment |
c910ceff | 1067 | promise& |
84b63c01 | 1068 | operator=(promise&& __rhs) noexcept |
c910ceff JW |
1069 | { |
1070 | promise(std::move(__rhs)).swap(*this); | |
1071 | return *this; | |
1072 | } | |
1073 | ||
1074 | promise& operator=(const promise&) = delete; | |
1075 | ||
1076 | void | |
84b63c01 | 1077 | swap(promise& __rhs) noexcept |
c910ceff JW |
1078 | { |
1079 | _M_future.swap(__rhs._M_future); | |
1080 | _M_storage.swap(__rhs._M_storage); | |
1081 | } | |
1082 | ||
c36abf03 | 1083 | // Retrieving the result |
b3eed6fe | 1084 | future<_Res> |
c910ceff | 1085 | get_future() |
b3eed6fe | 1086 | { return future<_Res>(_M_future); } |
c910ceff | 1087 | |
c36abf03 | 1088 | // Setting the result |
c910ceff | 1089 | void |
c36abf03 | 1090 | set_value(const _Res& __r) |
4e48c109 | 1091 | { _M_future->_M_set_result(_State::__setter(this, __r)); } |
c910ceff JW |
1092 | |
1093 | void | |
c36abf03 | 1094 | set_value(_Res&& __r) |
4e48c109 | 1095 | { _M_future->_M_set_result(_State::__setter(this, std::move(__r))); } |
c910ceff JW |
1096 | |
1097 | void | |
1098 | set_exception(exception_ptr __p) | |
4e48c109 | 1099 | { _M_future->_M_set_result(_State::__setter(__p, this)); } |
9db7c931 JW |
1100 | |
1101 | void | |
1102 | set_value_at_thread_exit(const _Res& __r) | |
1103 | { | |
1104 | _M_future->_M_set_delayed_result(_State::__setter(this, __r), | |
1105 | _M_future); | |
1106 | } | |
1107 | ||
1108 | void | |
1109 | set_value_at_thread_exit(_Res&& __r) | |
1110 | { | |
1111 | _M_future->_M_set_delayed_result( | |
1112 | _State::__setter(this, std::move(__r)), _M_future); | |
1113 | } | |
1114 | ||
1115 | void | |
1116 | set_exception_at_thread_exit(exception_ptr __p) | |
1117 | { | |
1118 | _M_future->_M_set_delayed_result(_State::__setter(__p, this), | |
1119 | _M_future); | |
1120 | } | |
c910ceff JW |
1121 | }; |
1122 | ||
19501406 PC |
1123 | template<typename _Res> |
1124 | inline void | |
84b63c01 | 1125 | swap(promise<_Res>& __x, promise<_Res>& __y) noexcept |
19501406 PC |
1126 | { __x.swap(__y); } |
1127 | ||
135a0d0a PC |
1128 | template<typename _Res, typename _Alloc> |
1129 | struct uses_allocator<promise<_Res>, _Alloc> | |
1130 | : public true_type { }; | |
1131 | ||
1132 | ||
c36abf03 BK |
1133 | /// Partial specialization for promise<R&> |
1134 | template<typename _Res> | |
1135 | class promise<_Res&> | |
c910ceff | 1136 | { |
c4d9f419 JW |
1137 | typedef __future_base::_State_base _State; |
1138 | typedef __future_base::_Result<_Res&> _Res_type; | |
1139 | typedef __future_base::_Ptr<_Res_type> _Ptr_type; | |
b3eed6fe | 1140 | template<typename, typename> friend class _State::_Setter; |
c36abf03 BK |
1141 | |
1142 | shared_ptr<_State> _M_future; | |
b3eed6fe | 1143 | _Ptr_type _M_storage; |
c36abf03 | 1144 | |
c910ceff JW |
1145 | public: |
1146 | promise() | |
19501406 PC |
1147 | : _M_future(std::make_shared<_State>()), |
1148 | _M_storage(new _Res_type()) | |
c910ceff JW |
1149 | { } |
1150 | ||
84b63c01 | 1151 | promise(promise&& __rhs) noexcept |
faa00511 | 1152 | : _M_future(std::move(__rhs._M_future)), |
c36abf03 | 1153 | _M_storage(std::move(__rhs._M_storage)) |
c910ceff JW |
1154 | { } |
1155 | ||
c910ceff | 1156 | template<typename _Allocator> |
b3eed6fe JW |
1157 | promise(allocator_arg_t, const _Allocator& __a) |
1158 | : _M_future(std::allocate_shared<_State>(__a)), | |
135a0d0a | 1159 | _M_storage(__future_base::_S_allocate_result<_Res&>(__a)) |
b3eed6fe | 1160 | { } |
c910ceff | 1161 | |
376d7c51 JW |
1162 | template<typename _Allocator> |
1163 | promise(allocator_arg_t, const _Allocator&, promise&& __rhs) | |
1164 | : _M_future(std::move(__rhs._M_future)), | |
1165 | _M_storage(std::move(__rhs._M_storage)) | |
1166 | { } | |
1167 | ||
c910ceff JW |
1168 | promise(const promise&) = delete; |
1169 | ||
1170 | ~promise() | |
1171 | { | |
1172 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
1173 | _M_future->_M_break_promise(std::move(_M_storage)); | |
1174 | } | |
1175 | ||
c36abf03 | 1176 | // Assignment |
c910ceff | 1177 | promise& |
84b63c01 | 1178 | operator=(promise&& __rhs) noexcept |
c910ceff JW |
1179 | { |
1180 | promise(std::move(__rhs)).swap(*this); | |
1181 | return *this; | |
1182 | } | |
1183 | ||
1184 | promise& operator=(const promise&) = delete; | |
1185 | ||
1186 | void | |
84b63c01 | 1187 | swap(promise& __rhs) noexcept |
c910ceff JW |
1188 | { |
1189 | _M_future.swap(__rhs._M_future); | |
1190 | _M_storage.swap(__rhs._M_storage); | |
1191 | } | |
1192 | ||
c36abf03 | 1193 | // Retrieving the result |
b3eed6fe | 1194 | future<_Res&> |
c910ceff | 1195 | get_future() |
b3eed6fe | 1196 | { return future<_Res&>(_M_future); } |
c910ceff | 1197 | |
c36abf03 | 1198 | // Setting the result |
c910ceff | 1199 | void |
c36abf03 | 1200 | set_value(_Res& __r) |
4e48c109 | 1201 | { _M_future->_M_set_result(_State::__setter(this, __r)); } |
c910ceff JW |
1202 | |
1203 | void | |
1204 | set_exception(exception_ptr __p) | |
4e48c109 | 1205 | { _M_future->_M_set_result(_State::__setter(__p, this)); } |
9db7c931 JW |
1206 | |
1207 | void | |
1208 | set_value_at_thread_exit(_Res& __r) | |
1209 | { | |
1210 | _M_future->_M_set_delayed_result(_State::__setter(this, __r), | |
1211 | _M_future); | |
1212 | } | |
1213 | ||
1214 | void | |
1215 | set_exception_at_thread_exit(exception_ptr __p) | |
1216 | { | |
1217 | _M_future->_M_set_delayed_result(_State::__setter(__p, this), | |
1218 | _M_future); | |
1219 | } | |
c910ceff JW |
1220 | }; |
1221 | ||
c36abf03 | 1222 | /// Explicit specialization for promise<void> |
c910ceff JW |
1223 | template<> |
1224 | class promise<void> | |
1225 | { | |
c4d9f419 JW |
1226 | typedef __future_base::_State_base _State; |
1227 | typedef __future_base::_Result<void> _Res_type; | |
1228 | typedef __future_base::_Ptr<_Res_type> _Ptr_type; | |
b3eed6fe | 1229 | template<typename, typename> friend class _State::_Setter; |
c36abf03 | 1230 | |
b3eed6fe JW |
1231 | shared_ptr<_State> _M_future; |
1232 | _Ptr_type _M_storage; | |
c36abf03 | 1233 | |
c910ceff JW |
1234 | public: |
1235 | promise() | |
c36abf03 | 1236 | : _M_future(std::make_shared<_State>()), |
b3eed6fe | 1237 | _M_storage(new _Res_type()) |
c910ceff JW |
1238 | { } |
1239 | ||
84b63c01 | 1240 | promise(promise&& __rhs) noexcept |
c910ceff | 1241 | : _M_future(std::move(__rhs._M_future)), |
19501406 | 1242 | _M_storage(std::move(__rhs._M_storage)) |
c910ceff JW |
1243 | { } |
1244 | ||
c910ceff | 1245 | template<typename _Allocator> |
b3eed6fe JW |
1246 | promise(allocator_arg_t, const _Allocator& __a) |
1247 | : _M_future(std::allocate_shared<_State>(__a)), | |
135a0d0a | 1248 | _M_storage(__future_base::_S_allocate_result<void>(__a)) |
b3eed6fe | 1249 | { } |
c910ceff | 1250 | |
1b5dc776 JW |
1251 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1252 | // 2095. missing constructors needed for uses-allocator construction | |
376d7c51 JW |
1253 | template<typename _Allocator> |
1254 | promise(allocator_arg_t, const _Allocator&, promise&& __rhs) | |
1255 | : _M_future(std::move(__rhs._M_future)), | |
1256 | _M_storage(std::move(__rhs._M_storage)) | |
1257 | { } | |
1258 | ||
c910ceff JW |
1259 | promise(const promise&) = delete; |
1260 | ||
1261 | ~promise() | |
1262 | { | |
1263 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
1264 | _M_future->_M_break_promise(std::move(_M_storage)); | |
1265 | } | |
1266 | ||
c36abf03 | 1267 | // Assignment |
c910ceff | 1268 | promise& |
84b63c01 | 1269 | operator=(promise&& __rhs) noexcept |
c910ceff JW |
1270 | { |
1271 | promise(std::move(__rhs)).swap(*this); | |
1272 | return *this; | |
1273 | } | |
1274 | ||
1275 | promise& operator=(const promise&) = delete; | |
1276 | ||
1277 | void | |
84b63c01 | 1278 | swap(promise& __rhs) noexcept |
c910ceff JW |
1279 | { |
1280 | _M_future.swap(__rhs._M_future); | |
1281 | _M_storage.swap(__rhs._M_storage); | |
1282 | } | |
1283 | ||
c36abf03 | 1284 | // Retrieving the result |
b3eed6fe | 1285 | future<void> |
c910ceff | 1286 | get_future() |
b3eed6fe | 1287 | { return future<void>(_M_future); } |
c910ceff | 1288 | |
c36abf03 | 1289 | // Setting the result |
b3eed6fe JW |
1290 | void set_value(); |
1291 | ||
c910ceff | 1292 | void |
b3eed6fe | 1293 | set_exception(exception_ptr __p) |
4e48c109 | 1294 | { _M_future->_M_set_result(_State::__setter(__p, this)); } |
9db7c931 JW |
1295 | |
1296 | void | |
1297 | set_value_at_thread_exit(); | |
1298 | ||
1299 | void | |
1300 | set_exception_at_thread_exit(exception_ptr __p) | |
1301 | { | |
1302 | _M_future->_M_set_delayed_result(_State::__setter(__p, this), | |
1303 | _M_future); | |
1304 | } | |
b3eed6fe | 1305 | }; |
c910ceff | 1306 | |
b3eed6fe JW |
1307 | // set void |
1308 | template<> | |
e9599233 | 1309 | struct __future_base::_State_base::_Setter<void, void> |
b3eed6fe | 1310 | { |
9131b509 | 1311 | promise<void>::_Ptr_type operator()() const |
c910ceff | 1312 | { |
e9599233 | 1313 | _State_base::_S_check(_M_promise->_M_future); |
b3eed6fe | 1314 | return std::move(_M_promise->_M_storage); |
c910ceff JW |
1315 | } |
1316 | ||
b3eed6fe | 1317 | promise<void>* _M_promise; |
c910ceff JW |
1318 | }; |
1319 | ||
b3eed6fe JW |
1320 | inline void |
1321 | promise<void>::set_value() | |
4e48c109 | 1322 | { _M_future->_M_set_result(_State::_Setter<void, void>{ this }); } |
b3eed6fe | 1323 | |
9db7c931 JW |
1324 | inline void |
1325 | promise<void>::set_value_at_thread_exit() | |
1326 | { | |
1327 | _M_future->_M_set_delayed_result(_State::_Setter<void, void>{this}, | |
1328 | _M_future); | |
1329 | } | |
1330 | ||
4e48c109 | 1331 | template<typename _Ptr_type, typename _Fn, typename _Res> |
b3eed6fe | 1332 | struct __future_base::_Task_setter |
c910ceff | 1333 | { |
9db7c931 | 1334 | // Invoke the function and provide the result to the caller. |
9131b509 | 1335 | _Ptr_type operator()() const |
c910ceff | 1336 | { |
aaad548e | 1337 | __try |
19501406 | 1338 | { |
4e48c109 | 1339 | (*_M_result)->_M_set((*_M_fn)()); |
19501406 | 1340 | } |
315eb4bb JW |
1341 | __catch(const __cxxabiv1::__forced_unwind&) |
1342 | { | |
1343 | __throw_exception_again; // will cause broken_promise | |
1344 | } | |
19501406 PC |
1345 | __catch(...) |
1346 | { | |
4e48c109 | 1347 | (*_M_result)->_M_error = current_exception(); |
19501406 | 1348 | } |
4e48c109 | 1349 | return std::move(*_M_result); |
c910ceff | 1350 | } |
4e48c109 JW |
1351 | _Ptr_type* _M_result; |
1352 | _Fn* _M_fn; | |
c910ceff JW |
1353 | }; |
1354 | ||
4e48c109 JW |
1355 | template<typename _Ptr_type, typename _Fn> |
1356 | struct __future_base::_Task_setter<_Ptr_type, _Fn, void> | |
c910ceff | 1357 | { |
9131b509 | 1358 | _Ptr_type operator()() const |
c910ceff | 1359 | { |
aaad548e | 1360 | __try |
19501406 | 1361 | { |
4e48c109 | 1362 | (*_M_fn)(); |
19501406 | 1363 | } |
315eb4bb JW |
1364 | __catch(const __cxxabiv1::__forced_unwind&) |
1365 | { | |
1366 | __throw_exception_again; // will cause broken_promise | |
1367 | } | |
19501406 PC |
1368 | __catch(...) |
1369 | { | |
4e48c109 | 1370 | (*_M_result)->_M_error = current_exception(); |
19501406 | 1371 | } |
4e48c109 | 1372 | return std::move(*_M_result); |
c910ceff | 1373 | } |
4e48c109 JW |
1374 | _Ptr_type* _M_result; |
1375 | _Fn* _M_fn; | |
c910ceff JW |
1376 | }; |
1377 | ||
9db7c931 | 1378 | // Holds storage for a packaged_task's result. |
b3eed6fe | 1379 | template<typename _Res, typename... _Args> |
aaad548e | 1380 | struct __future_base::_Task_state_base<_Res(_Args...)> |
e9599233 | 1381 | : __future_base::_State_base |
b3eed6fe JW |
1382 | { |
1383 | typedef _Res _Res_type; | |
1384 | ||
aaad548e JW |
1385 | template<typename _Alloc> |
1386 | _Task_state_base(const _Alloc& __a) | |
1387 | : _M_result(_S_allocate_result<_Res>(__a)) | |
1388 | { } | |
b3eed6fe | 1389 | |
9db7c931 | 1390 | // Invoke the stored task and make the state ready. |
aaad548e | 1391 | virtual void |
9db7c931 JW |
1392 | _M_run(_Args&&... __args) = 0; |
1393 | ||
1394 | // Invoke the stored task and make the state ready at thread exit. | |
1395 | virtual void | |
1396 | _M_run_delayed(_Args&&... __args, weak_ptr<_State_base>) = 0; | |
b3eed6fe | 1397 | |
aaad548e JW |
1398 | virtual shared_ptr<_Task_state_base> |
1399 | _M_reset() = 0; | |
1400 | ||
1401 | typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type; | |
1402 | _Ptr_type _M_result; | |
1403 | }; | |
1404 | ||
9db7c931 | 1405 | // Holds a packaged_task's stored task. |
aaad548e JW |
1406 | template<typename _Fn, typename _Alloc, typename _Res, typename... _Args> |
1407 | struct __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)> final | |
1408 | : __future_base::_Task_state_base<_Res(_Args...)> | |
1409 | { | |
f7e68d08 JW |
1410 | template<typename _Fn2> |
1411 | _Task_state(_Fn2&& __fn, const _Alloc& __a) | |
1412 | : _Task_state_base<_Res(_Args...)>(__a), | |
1413 | _M_impl(std::forward<_Fn2>(__fn), __a) | |
1414 | { } | |
aaad548e JW |
1415 | |
1416 | private: | |
1417 | virtual void | |
9db7c931 | 1418 | _M_run(_Args&&... __args) |
b3eed6fe | 1419 | { |
5579170b JW |
1420 | auto __boundfn = [&] () -> typename result_of<_Fn(_Args&&...)>::type { |
1421 | return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...); | |
1422 | }; | |
4e48c109 | 1423 | this->_M_set_result(_S_task_setter(this->_M_result, __boundfn)); |
b3eed6fe JW |
1424 | } |
1425 | ||
9db7c931 JW |
1426 | virtual void |
1427 | _M_run_delayed(_Args&&... __args, weak_ptr<_State_base> __self) | |
1428 | { | |
5579170b JW |
1429 | auto __boundfn = [&] () -> typename result_of<_Fn(_Args&&...)>::type { |
1430 | return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...); | |
1431 | }; | |
9db7c931 JW |
1432 | this->_M_set_delayed_result(_S_task_setter(this->_M_result, __boundfn), |
1433 | std::move(__self)); | |
1434 | } | |
1435 | ||
aaad548e JW |
1436 | virtual shared_ptr<_Task_state_base<_Res(_Args...)>> |
1437 | _M_reset(); | |
b3eed6fe | 1438 | |
aaad548e JW |
1439 | struct _Impl : _Alloc |
1440 | { | |
f7e68d08 JW |
1441 | template<typename _Fn2> |
1442 | _Impl(_Fn2&& __fn, const _Alloc& __a) | |
1443 | : _Alloc(__a), _M_fn(std::forward<_Fn2>(__fn)) { } | |
aaad548e JW |
1444 | _Fn _M_fn; |
1445 | } _M_impl; | |
b3eed6fe | 1446 | }; |
c36abf03 | 1447 | |
f7e68d08 JW |
1448 | template<typename _Signature, typename _Fn, typename _Alloc> |
1449 | static shared_ptr<__future_base::_Task_state_base<_Signature>> | |
1450 | __create_task_state(_Fn&& __fn, const _Alloc& __a) | |
1451 | { | |
1452 | typedef typename decay<_Fn>::type _Fn2; | |
1453 | typedef __future_base::_Task_state<_Fn2, _Alloc, _Signature> _State; | |
1454 | return std::allocate_shared<_State>(__a, std::forward<_Fn>(__fn), __a); | |
1455 | } | |
aaad548e JW |
1456 | |
1457 | template<typename _Fn, typename _Alloc, typename _Res, typename... _Args> | |
1458 | shared_ptr<__future_base::_Task_state_base<_Res(_Args...)>> | |
1459 | __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)>::_M_reset() | |
1460 | { | |
1461 | return __create_task_state<_Res(_Args...)>(std::move(_M_impl._M_fn), | |
1462 | static_cast<_Alloc&>(_M_impl)); | |
1463 | } | |
1464 | ||
376d7c51 | 1465 | template<typename _Task, typename _Fn, bool |
aaad548e | 1466 | = is_same<_Task, typename decay<_Fn>::type>::value> |
c4d9f419 | 1467 | struct __constrain_pkgdtask |
376d7c51 JW |
1468 | { typedef void __type; }; |
1469 | ||
1470 | template<typename _Task, typename _Fn> | |
c4d9f419 | 1471 | struct __constrain_pkgdtask<_Task, _Fn, true> |
376d7c51 JW |
1472 | { }; |
1473 | ||
3259554a | 1474 | /// packaged_task |
c36abf03 BK |
1475 | template<typename _Res, typename... _ArgTypes> |
1476 | class packaged_task<_Res(_ArgTypes...)> | |
c910ceff | 1477 | { |
aaad548e | 1478 | typedef __future_base::_Task_state_base<_Res(_ArgTypes...)> _State_type; |
b3eed6fe | 1479 | shared_ptr<_State_type> _M_state; |
c36abf03 | 1480 | |
c910ceff | 1481 | public: |
c36abf03 | 1482 | // Construction and destruction |
84b63c01 | 1483 | packaged_task() noexcept { } |
c910ceff | 1484 | |
1b5dc776 JW |
1485 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1486 | // 2095. missing constructors needed for uses-allocator construction | |
376d7c51 | 1487 | template<typename _Allocator> |
aaad548e JW |
1488 | packaged_task(allocator_arg_t, const _Allocator& __a) noexcept |
1489 | { } | |
376d7c51 JW |
1490 | |
1491 | template<typename _Fn, typename = typename | |
aaad548e JW |
1492 | __constrain_pkgdtask<packaged_task, _Fn>::__type> |
1493 | explicit | |
1494 | packaged_task(_Fn&& __fn) | |
f7e68d08 JW |
1495 | : packaged_task(allocator_arg, std::allocator<int>(), |
1496 | std::forward<_Fn>(__fn)) | |
aaad548e | 1497 | { } |
c910ceff | 1498 | |
1b5dc776 JW |
1499 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1500 | // 2097. packaged_task constructors should be constrained | |
e6508eaf | 1501 | // 2407. [this constructor should not be] explicit |
aaad548e JW |
1502 | template<typename _Fn, typename _Alloc, typename = typename |
1503 | __constrain_pkgdtask<packaged_task, _Fn>::__type> | |
aaad548e JW |
1504 | packaged_task(allocator_arg_t, const _Alloc& __a, _Fn&& __fn) |
1505 | : _M_state(__create_task_state<_Res(_ArgTypes...)>( | |
1506 | std::forward<_Fn>(__fn), __a)) | |
1507 | { } | |
c910ceff | 1508 | |
b3eed6fe JW |
1509 | ~packaged_task() |
1510 | { | |
1511 | if (static_cast<bool>(_M_state) && !_M_state.unique()) | |
aaad548e | 1512 | _M_state->_M_break_promise(std::move(_M_state->_M_result)); |
b3eed6fe | 1513 | } |
c910ceff | 1514 | |
c36abf03 | 1515 | // No copy |
376d7c51 JW |
1516 | packaged_task(const packaged_task&) = delete; |
1517 | packaged_task& operator=(const packaged_task&) = delete; | |
1518 | ||
1519 | template<typename _Allocator> | |
aaad548e JW |
1520 | packaged_task(allocator_arg_t, const _Allocator&, |
1521 | const packaged_task&) = delete; | |
c910ceff | 1522 | |
c36abf03 | 1523 | // Move support |
84b63c01 | 1524 | packaged_task(packaged_task&& __other) noexcept |
c910ceff JW |
1525 | { this->swap(__other); } |
1526 | ||
376d7c51 | 1527 | template<typename _Allocator> |
aaad548e JW |
1528 | packaged_task(allocator_arg_t, const _Allocator&, |
1529 | packaged_task&& __other) noexcept | |
1530 | { this->swap(__other); } | |
376d7c51 | 1531 | |
84b63c01 | 1532 | packaged_task& operator=(packaged_task&& __other) noexcept |
c910ceff | 1533 | { |
aaad548e JW |
1534 | packaged_task(std::move(__other)).swap(*this); |
1535 | return *this; | |
c910ceff JW |
1536 | } |
1537 | ||
1538 | void | |
84b63c01 | 1539 | swap(packaged_task& __other) noexcept |
b3eed6fe | 1540 | { _M_state.swap(__other._M_state); } |
c910ceff | 1541 | |
7a0269de | 1542 | bool |
84b63c01 | 1543 | valid() const noexcept |
7a0269de | 1544 | { return static_cast<bool>(_M_state); } |
c910ceff | 1545 | |
c36abf03 | 1546 | // Result retrieval |
b3eed6fe | 1547 | future<_Res> |
c910ceff | 1548 | get_future() |
b3eed6fe | 1549 | { return future<_Res>(_M_state); } |
c910ceff | 1550 | |
c36abf03 | 1551 | // Execution |
c910ceff JW |
1552 | void |
1553 | operator()(_ArgTypes... __args) | |
1554 | { | |
aaad548e JW |
1555 | __future_base::_State_base::_S_check(_M_state); |
1556 | _M_state->_M_run(std::forward<_ArgTypes>(__args)...); | |
b3eed6fe | 1557 | } |
8d1b99e2 | 1558 | |
9db7c931 JW |
1559 | void |
1560 | make_ready_at_thread_exit(_ArgTypes... __args) | |
1561 | { | |
1562 | __future_base::_State_base::_S_check(_M_state); | |
1563 | _M_state->_M_run_delayed(std::forward<_ArgTypes>(__args)..., _M_state); | |
1564 | } | |
1565 | ||
b3eed6fe JW |
1566 | void |
1567 | reset() | |
1568 | { | |
aaad548e JW |
1569 | __future_base::_State_base::_S_check(_M_state); |
1570 | packaged_task __tmp; | |
1571 | __tmp._M_state = _M_state; | |
1572 | _M_state = _M_state->_M_reset(); | |
b3eed6fe JW |
1573 | } |
1574 | }; | |
1575 | ||
94a86be0 | 1576 | /// swap |
19501406 | 1577 | template<typename _Res, typename... _ArgTypes> |
4e4d27aa | 1578 | inline void |
19501406 | 1579 | swap(packaged_task<_Res(_ArgTypes...)>& __x, |
84b63c01 | 1580 | packaged_task<_Res(_ArgTypes...)>& __y) noexcept |
19501406 | 1581 | { __x.swap(__y); } |
135a0d0a PC |
1582 | |
1583 | template<typename _Res, typename _Alloc> | |
1584 | struct uses_allocator<packaged_task<_Res>, _Alloc> | |
1585 | : public true_type { }; | |
1586 | ||
1587 | ||
9db7c931 JW |
1588 | // Shared state created by std::async(). |
1589 | // Holds a deferred function and storage for its result. | |
4880236e | 1590 | template<typename _BoundFn, typename _Res> |
a58a38b3 JW |
1591 | class __future_base::_Deferred_state final |
1592 | : public __future_base::_State_base | |
b3eed6fe JW |
1593 | { |
1594 | public: | |
b3eed6fe | 1595 | explicit |
4880236e | 1596 | _Deferred_state(_BoundFn&& __fn) |
b3eed6fe JW |
1597 | : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)) |
1598 | { } | |
1599 | ||
1600 | private: | |
c4d9f419 | 1601 | typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type; |
b3eed6fe | 1602 | _Ptr_type _M_result; |
4880236e | 1603 | _BoundFn _M_fn; |
b3eed6fe | 1604 | |
f2f08be7 | 1605 | // Run the deferred function. |
b3eed6fe | 1606 | virtual void |
f2f08be7 | 1607 | _M_complete_async() |
b3eed6fe | 1608 | { |
9db7c931 JW |
1609 | // Multiple threads can call a waiting function on the future and |
1610 | // reach this point at the same time. The call_once in _M_set_result | |
1611 | // ensures only the first one run the deferred function, stores the | |
1612 | // result in _M_result, swaps that with the base _M_result and makes | |
1613 | // the state ready. Tell _M_set_result to ignore failure so all later | |
1614 | // calls do nothing. | |
4880236e | 1615 | _M_set_result(_S_task_setter(_M_result, _M_fn), true); |
b3eed6fe | 1616 | } |
f2f08be7 | 1617 | |
9db7c931 JW |
1618 | // Caller should check whether the state is ready first, because this |
1619 | // function will return true even after the deferred function has run. | |
eae801ba | 1620 | virtual bool _M_is_deferred_future() const { return true; } |
b3eed6fe JW |
1621 | }; |
1622 | ||
9db7c931 | 1623 | // Common functionality hoisted out of the _Async_state_impl template. |
f2f08be7 JW |
1624 | class __future_base::_Async_state_commonV2 |
1625 | : public __future_base::_State_base | |
488b3e65 JW |
1626 | { |
1627 | protected: | |
f2f08be7 | 1628 | ~_Async_state_commonV2() = default; |
488b3e65 | 1629 | |
f2f08be7 | 1630 | // Make waiting functions block until the thread completes, as if joined. |
9db7c931 JW |
1631 | // |
1632 | // This function is used by wait() to satisfy the first requirement below | |
1633 | // and by wait_for() / wait_until() to satisfy the second. | |
1634 | // | |
1635 | // [futures.async]: | |
1636 | // | |
1637 | // — a call to a waiting function on an asynchronous return object that | |
1638 | // shares the shared state created by this async call shall block until | |
1639 | // the associated thread has completed, as if joined, or else time out. | |
1640 | // | |
1641 | // — the associated thread completion synchronizes with the return from | |
1642 | // the first function that successfully detects the ready status of the | |
1643 | // shared state or with the return from the last function that releases | |
1644 | // the shared state, whichever happens first. | |
f2f08be7 | 1645 | virtual void _M_complete_async() { _M_join(); } |
488b3e65 | 1646 | |
93e95400 | 1647 | void _M_join() { std::call_once(_M_once, &thread::join, &_M_thread); } |
488b3e65 JW |
1648 | |
1649 | thread _M_thread; | |
1650 | once_flag _M_once; | |
1651 | }; | |
1652 | ||
9db7c931 JW |
1653 | // Shared state created by std::async(). |
1654 | // Starts a new thread that runs a function and makes the shared state ready. | |
4880236e | 1655 | template<typename _BoundFn, typename _Res> |
488b3e65 | 1656 | class __future_base::_Async_state_impl final |
f2f08be7 | 1657 | : public __future_base::_Async_state_commonV2 |
b3eed6fe JW |
1658 | { |
1659 | public: | |
faa00511 | 1660 | explicit |
488b3e65 JW |
1661 | _Async_state_impl(_BoundFn&& __fn) |
1662 | : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)) | |
b3eed6fe | 1663 | { |
488b3e65 | 1664 | _M_thread = std::thread{ [this] { |
315eb4bb JW |
1665 | __try |
1666 | { | |
1667 | _M_set_result(_S_task_setter(_M_result, _M_fn)); | |
1668 | } | |
1669 | __catch (const __cxxabiv1::__forced_unwind&) | |
1670 | { | |
1671 | // make the shared state ready on thread cancellation | |
1672 | if (static_cast<bool>(_M_result)) | |
1673 | this->_M_break_promise(std::move(_M_result)); | |
1674 | __throw_exception_again; | |
1675 | } | |
488b3e65 | 1676 | } }; |
c910ceff JW |
1677 | } |
1678 | ||
9db7c931 JW |
1679 | // Must not destroy _M_result and _M_fn until the thread finishes. |
1680 | // Call join() directly rather than through _M_join() because no other | |
1681 | // thread can be referring to this state if it is being destroyed. | |
1682 | ~_Async_state_impl() { if (_M_thread.joinable()) _M_thread.join(); } | |
277f43d2 | 1683 | |
488b3e65 | 1684 | private: |
c4d9f419 | 1685 | typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type; |
b3eed6fe | 1686 | _Ptr_type _M_result; |
4880236e | 1687 | _BoundFn _M_fn; |
c910ceff JW |
1688 | }; |
1689 | ||
4880236e JW |
1690 | template<typename _BoundFn> |
1691 | inline std::shared_ptr<__future_base::_State_base> | |
1692 | __future_base::_S_make_deferred_state(_BoundFn&& __fn) | |
1693 | { | |
1694 | typedef typename remove_reference<_BoundFn>::type __fn_type; | |
1695 | typedef _Deferred_state<__fn_type> __state_type; | |
1696 | return std::make_shared<__state_type>(std::move(__fn)); | |
1697 | } | |
1698 | ||
1699 | template<typename _BoundFn> | |
1700 | inline std::shared_ptr<__future_base::_State_base> | |
1701 | __future_base::_S_make_async_state(_BoundFn&& __fn) | |
1702 | { | |
1703 | typedef typename remove_reference<_BoundFn>::type __fn_type; | |
488b3e65 | 1704 | typedef _Async_state_impl<__fn_type> __state_type; |
4880236e JW |
1705 | return std::make_shared<__state_type>(std::move(__fn)); |
1706 | } | |
1707 | ||
1708 | ||
faa00511 | 1709 | /// async |
b3eed6fe | 1710 | template<typename _Fn, typename... _Args> |
75eb6443 | 1711 | future<__async_result_of<_Fn, _Args...>> |
b3eed6fe JW |
1712 | async(launch __policy, _Fn&& __fn, _Args&&... __args) |
1713 | { | |
e9599233 | 1714 | std::shared_ptr<__future_base::_State_base> __state; |
f6341d8d | 1715 | if ((__policy & launch::async) == launch::async) |
19501406 | 1716 | { |
6fbd5984 JW |
1717 | __try |
1718 | { | |
5579170b JW |
1719 | __state = __future_base::_S_make_async_state( |
1720 | std::thread::__make_invoker(std::forward<_Fn>(__fn), | |
1721 | std::forward<_Args>(__args)...) | |
1722 | ); | |
6fbd5984 JW |
1723 | } |
1724 | #if __cpp_exceptions | |
1725 | catch(const system_error& __e) | |
1726 | { | |
1727 | if (__e.code() != errc::resource_unavailable_try_again | |
1728 | || (__policy & launch::deferred) != launch::deferred) | |
1729 | throw; | |
1730 | } | |
1731 | #endif | |
19501406 | 1732 | } |
6fbd5984 | 1733 | if (!__state) |
19501406 | 1734 | { |
5579170b JW |
1735 | __state = __future_base::_S_make_deferred_state( |
1736 | std::thread::__make_invoker(std::forward<_Fn>(__fn), | |
1737 | std::forward<_Args>(__args)...)); | |
19501406 | 1738 | } |
75eb6443 | 1739 | return future<__async_result_of<_Fn, _Args...>>(__state); |
b3eed6fe JW |
1740 | } |
1741 | ||
94a86be0 | 1742 | /// async, potential overload |
b3eed6fe | 1743 | template<typename _Fn, typename... _Args> |
75eb6443 | 1744 | inline future<__async_result_of<_Fn, _Args...>> |
b3eed6fe JW |
1745 | async(_Fn&& __fn, _Args&&... __args) |
1746 | { | |
75eb6443 JW |
1747 | return std::async(launch::async|launch::deferred, |
1748 | std::forward<_Fn>(__fn), | |
1749 | std::forward<_Args>(__args)...); | |
b3eed6fe JW |
1750 | } |
1751 | ||
f2f08be7 | 1752 | #endif // _GLIBCXX_ASYNC_ABI_COMPAT |
c910ceff | 1753 | #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 |
a152e96f | 1754 | // && ATOMIC_INT_LOCK_FREE |
c910ceff | 1755 | |
41ca4246 | 1756 | // @} group futures |
12ffa228 BK |
1757 | _GLIBCXX_END_NAMESPACE_VERSION |
1758 | } // namespace | |
41ca4246 | 1759 | |
734f5023 | 1760 | #endif // C++11 |
c910ceff JW |
1761 | |
1762 | #endif // _GLIBCXX_FUTURE |