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