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