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