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