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