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