]>
Commit | Line | Data |
---|---|---|
c910ceff JW |
1 | // <future> -*- C++ -*- |
2 | ||
19501406 | 3 | // Copyright (C) 2009, 2010 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 | ||
34 | #ifndef __GXX_EXPERIMENTAL_CXX0X__ | |
ab65a4c7 | 35 | # include <bits/c++0x_warning.h> |
c910ceff JW |
36 | #else |
37 | ||
38 | #include <functional> | |
39 | #include <memory> | |
40 | #include <mutex> | |
b3eed6fe | 41 | #include <thread> |
c910ceff JW |
42 | #include <condition_variable> |
43 | #include <system_error> | |
44 | #include <exception> | |
afd88205 | 45 | #include <atomic> |
abcd7e08 | 46 | #include <bits/functexcept.h> |
c910ceff | 47 | |
53dc5044 PC |
48 | _GLIBCXX_BEGIN_NAMESPACE(std) |
49 | ||
c910ceff JW |
50 | /** |
51 | * @defgroup futures Futures | |
52 | * @ingroup concurrency | |
53 | * | |
54 | * Classes for futures support. | |
55 | * @{ | |
56 | */ | |
57 | ||
58 | /// Error code for futures | |
59 | enum class future_errc | |
b3eed6fe JW |
60 | { |
61 | broken_promise, | |
62 | future_already_retrieved, | |
63 | promise_already_satisfied, | |
64 | no_state | |
65 | }; | |
c910ceff | 66 | |
94a86be0 | 67 | /// Specialization. |
c910ceff JW |
68 | template<> |
69 | struct is_error_code_enum<future_errc> : public true_type { }; | |
70 | ||
71 | /// Points to a statically-allocated object derived from error_category. | |
94a86be0 BK |
72 | const error_category& |
73 | future_category(); | |
c910ceff | 74 | |
94a86be0 BK |
75 | /// Overload for make_error_code. |
76 | inline error_code | |
77 | make_error_code(future_errc __errc) | |
78 | { return error_code(static_cast<int>(__errc), future_category()); } | |
c910ceff | 79 | |
94a86be0 BK |
80 | /// Overload for make_error_condition. |
81 | inline error_condition | |
82 | make_error_condition(future_errc __errc) | |
83 | { return error_condition(static_cast<int>(__errc), future_category()); } | |
c910ceff | 84 | |
8d1b99e2 BK |
85 | /** |
86 | * @brief Exception type thrown by futures. | |
87 | * @ingroup exceptions | |
88 | */ | |
c910ceff JW |
89 | class future_error : public logic_error |
90 | { | |
c36abf03 | 91 | error_code _M_code; |
8d1b99e2 | 92 | |
c910ceff | 93 | public: |
b3eed6fe JW |
94 | explicit future_error(error_code __ec) |
95 | : logic_error("std::future_error"), _M_code(__ec) | |
c910ceff JW |
96 | { } |
97 | ||
8d1b99e2 | 98 | virtual ~future_error() throw(); |
c910ceff | 99 | |
8d1b99e2 BK |
100 | virtual const char* |
101 | what() const throw(); | |
c910ceff | 102 | |
8d1b99e2 BK |
103 | const error_code& |
104 | code() const throw() { return _M_code; } | |
c910ceff JW |
105 | }; |
106 | ||
3259554a | 107 | // Forward declarations. |
c36abf03 | 108 | template<typename _Res> |
b3eed6fe | 109 | class future; |
3259554a | 110 | |
c36abf03 | 111 | template<typename _Res> |
3259554a BK |
112 | class shared_future; |
113 | ||
b3eed6fe JW |
114 | template<typename _Res> |
115 | class atomic_future; | |
116 | ||
117 | template<typename _Signature> | |
3259554a BK |
118 | class packaged_task; |
119 | ||
c36abf03 | 120 | template<typename _Res> |
3259554a BK |
121 | class promise; |
122 | ||
94a86be0 BK |
123 | /// Launch code for futures |
124 | enum class launch | |
125 | { | |
126 | any, | |
127 | async, | |
128 | sync | |
129 | }; | |
130 | ||
131 | /// Status code for futures | |
132 | enum class future_status | |
133 | { | |
134 | ready, | |
135 | timeout, | |
136 | deferred | |
137 | }; | |
b3eed6fe JW |
138 | |
139 | template<typename _Fn, typename... _Args> | |
73c5c5bb | 140 | future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe JW |
141 | async(launch __policy, _Fn&& __fn, _Args&&... __args); |
142 | ||
143 | template<typename _Fn, typename... _Args> | |
73c5c5bb JW |
144 | typename |
145 | enable_if<!is_same<typename decay<_Fn>::type, launch>::value, | |
146 | future<decltype(std::declval<_Fn>()(std::declval<_Args>()...))> | |
147 | >::type | |
b3eed6fe JW |
148 | async(_Fn&& __fn, _Args&&... __args); |
149 | ||
41ca4246 BK |
150 | #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \ |
151 | && defined(_GLIBCXX_ATOMIC_BUILTINS_4) | |
152 | ||
c36abf03 BK |
153 | /// Base class and enclosing scope. |
154 | struct __future_base | |
c910ceff | 155 | { |
c36abf03 BK |
156 | /// Base class for results. |
157 | struct _Result_base | |
158 | { | |
159 | exception_ptr _M_error; | |
c910ceff | 160 | |
c36abf03 BK |
161 | _Result_base() = default; |
162 | _Result_base(const _Result_base&) = delete; | |
163 | _Result_base& operator=(const _Result_base&) = delete; | |
c910ceff | 164 | |
b3eed6fe | 165 | // _M_destroy() allows derived classes to control deallocation |
c36abf03 | 166 | virtual void _M_destroy() = 0; |
c910ceff | 167 | |
c36abf03 BK |
168 | struct _Deleter |
169 | { | |
170 | void operator()(_Result_base* __fr) const { __fr->_M_destroy(); } | |
171 | }; | |
c910ceff | 172 | |
c36abf03 BK |
173 | protected: |
174 | ~_Result_base(); | |
175 | }; | |
20f2653e | 176 | |
c36abf03 BK |
177 | /// Result. |
178 | template<typename _Res> | |
179 | struct _Result : _Result_base | |
180 | { | |
181 | private: | |
182 | typedef alignment_of<_Res> __a_of; | |
183 | typedef aligned_storage<sizeof(_Res), __a_of::value> __align_storage; | |
184 | typedef typename __align_storage::type __align_type; | |
185 | ||
186 | __align_type _M_storage; | |
187 | bool _M_initialized; | |
188 | ||
189 | public: | |
190 | _Result() : _M_initialized() { } | |
191 | ||
192 | ~_Result() | |
193 | { | |
194 | if (_M_initialized) | |
195 | _M_value().~_Res(); | |
196 | } | |
197 | ||
198 | // Return lvalue, future will add const or rvalue-reference | |
199 | _Res& | |
200 | _M_value() { return *static_cast<_Res*>(_M_addr()); } | |
201 | ||
202 | void | |
203 | _M_set(const _Res& __res) | |
204 | { | |
205 | ::new (_M_addr()) _Res(__res); | |
206 | _M_initialized = true; | |
207 | } | |
208 | ||
209 | void | |
210 | _M_set(_Res&& __res) | |
211 | { | |
abcd7e08 | 212 | ::new (_M_addr()) _Res(std::move(__res)); |
c36abf03 BK |
213 | _M_initialized = true; |
214 | } | |
215 | ||
216 | private: | |
217 | void _M_destroy() { delete this; } | |
218 | ||
219 | void* _M_addr() { return static_cast<void*>(&_M_storage); } | |
c910ceff JW |
220 | }; |
221 | ||
c36abf03 BK |
222 | // TODO: use template alias when available |
223 | /* | |
224 | template<typename _Res> | |
225 | using _Ptr = unique_ptr<_Res, _Result_base::_Deleter>; | |
226 | */ | |
227 | /// A unique_ptr based on the instantiating type. | |
228 | template<typename _Res> | |
229 | struct _Ptr | |
230 | { | |
231 | typedef unique_ptr<_Res, _Result_base::_Deleter> type; | |
232 | }; | |
c910ceff | 233 | |
b3eed6fe JW |
234 | /// Result_alloc. |
235 | template<typename _Res, typename _Alloc> | |
0fd76d8e | 236 | struct _Result_alloc : _Result<_Res>, _Alloc |
b3eed6fe JW |
237 | { |
238 | typedef typename _Alloc::template rebind<_Result_alloc>::other | |
239 | __allocator_type; | |
240 | ||
241 | explicit | |
0fd76d8e | 242 | _Result_alloc(const _Alloc& __a) : _Result<_Res>(), _Alloc(__a) |
b3eed6fe JW |
243 | { } |
244 | ||
245 | private: | |
246 | void _M_destroy() | |
247 | { | |
0fd76d8e | 248 | __allocator_type __a(*this); |
b3eed6fe JW |
249 | __a.destroy(this); |
250 | __a.deallocate(this, 1); | |
251 | } | |
135a0d0a | 252 | }; |
b3eed6fe JW |
253 | |
254 | template<typename _Res, typename _Allocator> | |
255 | static typename _Ptr<_Result_alloc<_Res, _Allocator>>::type | |
256 | _S_allocate_result(const _Allocator& __a) | |
257 | { | |
258 | typedef _Result_alloc<_Res, _Allocator> __result_type; | |
259 | typename __result_type::__allocator_type __a2(__a); | |
260 | __result_type* __p = __a2.allocate(1); | |
261 | __try | |
135a0d0a | 262 | { |
b3eed6fe JW |
263 | __a2.construct(__p, __a); |
264 | } | |
265 | __catch(...) | |
266 | { | |
267 | __a2.deallocate(__p, 1); | |
268 | __throw_exception_again; | |
269 | } | |
270 | return typename _Ptr<__result_type>::type(__p); | |
271 | } | |
b3eed6fe | 272 | |
c910ceff | 273 | |
c36abf03 BK |
274 | /// Shared state between a promise and one or more associated futures. |
275 | class _State | |
c910ceff | 276 | { |
c36abf03 | 277 | typedef _Ptr<_Result_base>::type _Ptr_type; |
c910ceff | 278 | |
c36abf03 BK |
279 | _Ptr_type _M_result; |
280 | mutex _M_mutex; | |
281 | condition_variable _M_cond; | |
282 | atomic_flag _M_retrieved; | |
b3eed6fe | 283 | once_flag _M_once; |
c910ceff | 284 | |
c36abf03 BK |
285 | public: |
286 | _State() : _M_result(), _M_retrieved(ATOMIC_FLAG_INIT) { } | |
287 | ||
288 | _State(const _State&) = delete; | |
289 | _State& operator=(const _State&) = delete; | |
c910ceff | 290 | |
c36abf03 BK |
291 | _Result_base& |
292 | wait() | |
c910ceff | 293 | { |
b3eed6fe | 294 | _M_run_deferred(); |
c36abf03 BK |
295 | unique_lock<mutex> __lock(_M_mutex); |
296 | if (!_M_ready()) | |
b3eed6fe | 297 | _M_cond.wait(__lock, std::bind<bool>(&_State::_M_ready, this)); |
c36abf03 | 298 | return *_M_result; |
c910ceff | 299 | } |
c910ceff | 300 | |
c36abf03 BK |
301 | template<typename _Rep, typename _Period> |
302 | bool | |
303 | wait_for(const chrono::duration<_Rep, _Period>& __rel) | |
304 | { | |
305 | unique_lock<mutex> __lock(_M_mutex); | |
b3eed6fe | 306 | auto __bound = std::bind<bool>(&_State::_M_ready, this); |
c36abf03 BK |
307 | return _M_ready() || _M_cond.wait_for(__lock, __rel, __bound); |
308 | } | |
c910ceff | 309 | |
c36abf03 BK |
310 | template<typename _Clock, typename _Duration> |
311 | bool | |
312 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) | |
313 | { | |
314 | unique_lock<mutex> __lock(_M_mutex); | |
b3eed6fe | 315 | auto __bound = std::bind<bool>(&_State::_M_ready, this); |
c36abf03 BK |
316 | return _M_ready() || _M_cond.wait_until(__lock, __abs, __bound); |
317 | } | |
c910ceff | 318 | |
c36abf03 | 319 | void |
b3eed6fe | 320 | _M_set_result(function<_Ptr_type()> __res, bool __ignore_failure = false) |
c910ceff | 321 | { |
b3eed6fe JW |
322 | bool __set = __ignore_failure; |
323 | // all calls to this function are serialized, | |
324 | // side-effects of invoking __res only happen once | |
1b3fad81 | 325 | call_once(_M_once, &_State::_M_do_set, this, ref(__res), |
b3eed6fe JW |
326 | ref(__set)); |
327 | if (!__set) | |
328 | __throw_future_error(int(future_errc::promise_already_satisfied)); | |
c910ceff JW |
329 | } |
330 | ||
c910ceff | 331 | void |
c36abf03 | 332 | _M_break_promise(_Ptr_type __res) |
c910ceff | 333 | { |
c36abf03 BK |
334 | if (static_cast<bool>(__res)) |
335 | { | |
b3eed6fe | 336 | error_code __ec(make_error_code(future_errc::broken_promise)); |
c36abf03 BK |
337 | __res->_M_error = copy_exception(future_error(__ec)); |
338 | { | |
339 | lock_guard<mutex> __lock(_M_mutex); | |
340 | _M_result.swap(__res); | |
341 | } | |
342 | _M_cond.notify_all(); | |
343 | } | |
c910ceff JW |
344 | } |
345 | ||
b3eed6fe | 346 | // Called when this object is passed to a future. |
c910ceff | 347 | void |
c36abf03 | 348 | _M_set_retrieved_flag() |
c910ceff | 349 | { |
c36abf03 BK |
350 | if (_M_retrieved.test_and_set()) |
351 | __throw_future_error(int(future_errc::future_already_retrieved)); | |
c910ceff JW |
352 | } |
353 | ||
b3eed6fe JW |
354 | template<typename _Res, typename _Arg> |
355 | struct _Setter; | |
356 | ||
357 | // set lvalues | |
358 | template<typename _Res, typename _Arg> | |
359 | struct _Setter<_Res, _Arg&> | |
360 | { | |
361 | // check this is only used by promise<R>::set_value(const R&) | |
362 | // or promise<R>::set_value(R&) | |
363 | static_assert(is_same<_Res, _Arg&>::value // promise<R&> | |
364 | || is_same<const _Res, _Arg>::value, // promise<R> | |
365 | "Invalid specialisation"); | |
366 | ||
367 | typename promise<_Res>::_Ptr_type operator()() | |
368 | { | |
369 | _State::_S_check(_M_promise->_M_future); | |
370 | _M_promise->_M_storage->_M_set(_M_arg); | |
371 | return std::move(_M_promise->_M_storage); | |
372 | } | |
373 | promise<_Res>* _M_promise; | |
374 | _Arg& _M_arg; | |
375 | }; | |
376 | ||
377 | // set rvalues | |
378 | template<typename _Res> | |
379 | struct _Setter<_Res, _Res&&> | |
380 | { | |
381 | typename promise<_Res>::_Ptr_type operator()() | |
382 | { | |
383 | _State::_S_check(_M_promise->_M_future); | |
384 | _M_promise->_M_storage->_M_set(std::move(_M_arg)); | |
385 | return std::move(_M_promise->_M_storage); | |
386 | } | |
387 | promise<_Res>* _M_promise; | |
388 | _Res& _M_arg; | |
389 | }; | |
390 | ||
391 | struct __exception_ptr_tag { }; | |
392 | ||
393 | // set exceptions | |
394 | template<typename _Res> | |
395 | struct _Setter<_Res, __exception_ptr_tag> | |
396 | { | |
397 | typename promise<_Res>::_Ptr_type operator()() | |
398 | { | |
399 | _State::_S_check(_M_promise->_M_future); | |
400 | _M_promise->_M_storage->_M_error = _M_ex; | |
401 | return std::move(_M_promise->_M_storage); | |
402 | } | |
403 | ||
404 | promise<_Res>* _M_promise; | |
405 | exception_ptr& _M_ex; | |
406 | }; | |
407 | ||
408 | template<typename _Res, typename _Arg> | |
409 | static _Setter<_Res, _Arg&&> | |
410 | __setter(promise<_Res>* __prom, _Arg&& __arg) | |
411 | { | |
412 | return _Setter<_Res, _Arg&&>{ __prom, __arg }; | |
413 | } | |
414 | ||
415 | template<typename _Res> | |
416 | static _Setter<_Res, __exception_ptr_tag> | |
417 | __setter(exception_ptr& __ex, promise<_Res>* __prom) | |
418 | { | |
419 | return _Setter<_Res, __exception_ptr_tag>{ __prom, __ex }; | |
420 | } | |
421 | ||
422 | static _Setter<void, void> | |
423 | __setter(promise<void>* __prom); | |
424 | ||
425 | template<typename _Tp> | |
426 | static bool | |
427 | _S_check(const shared_ptr<_Tp>& __p) | |
428 | { | |
429 | if (!static_cast<bool>(__p)) | |
430 | __throw_future_error((int)future_errc::no_state); | |
431 | } | |
432 | ||
c910ceff | 433 | private: |
b3eed6fe JW |
434 | void |
435 | _M_do_set(function<_Ptr_type()>& __f, bool& __set) | |
c36abf03 | 436 | { |
b3eed6fe JW |
437 | _Ptr_type __res = __f(); |
438 | { | |
439 | lock_guard<mutex> __lock(_M_mutex); | |
440 | _M_result.swap(__res); | |
441 | } | |
442 | _M_cond.notify_all(); | |
443 | __set = true; | |
c36abf03 | 444 | } |
c910ceff | 445 | |
c36abf03 | 446 | bool _M_ready() const { return static_cast<bool>(_M_result); } |
b3eed6fe JW |
447 | |
448 | virtual void _M_run_deferred() { } | |
c910ceff | 449 | }; |
b3eed6fe JW |
450 | |
451 | template<typename _Res> | |
452 | class _Deferred_state; | |
453 | ||
454 | template<typename _Res> | |
455 | class _Async_state; | |
456 | ||
457 | template<typename _Signature> | |
458 | class _Task_state; | |
459 | ||
460 | template<typename _StateT, typename _Res = typename _StateT::_Res_type> | |
461 | struct _Task_setter; | |
c36abf03 | 462 | }; |
c910ceff | 463 | |
c36abf03 | 464 | inline __future_base::_Result_base::~_Result_base() = default; |
c910ceff | 465 | |
c36abf03 BK |
466 | /// Partial specialization for reference types. |
467 | template<typename _Res> | |
468 | struct __future_base::_Result<_Res&> : __future_base::_Result_base | |
469 | { | |
470 | _Result() : _M_value_ptr() { } | |
c910ceff | 471 | |
b3eed6fe JW |
472 | void _M_set(_Res& __res) { _M_value_ptr = &__res; } |
473 | ||
474 | _Res& _M_get() { return *_M_value_ptr; } | |
475 | ||
476 | private: | |
c36abf03 BK |
477 | _Res* _M_value_ptr; |
478 | ||
c910ceff JW |
479 | void _M_destroy() { delete this; } |
480 | }; | |
481 | ||
c36abf03 | 482 | /// Explicit specialization for void. |
c910ceff | 483 | template<> |
c36abf03 | 484 | struct __future_base::_Result<void> : __future_base::_Result_base |
c910ceff | 485 | { |
c36abf03 | 486 | private: |
c910ceff JW |
487 | void _M_destroy() { delete this; } |
488 | }; | |
489 | ||
c36abf03 | 490 | |
b3eed6fe | 491 | /// Common implementation for future and shared_future. |
c36abf03 BK |
492 | template<typename _Res> |
493 | class __basic_future : public __future_base | |
c910ceff | 494 | { |
c36abf03 BK |
495 | protected: |
496 | typedef shared_ptr<_State> __state_type; | |
497 | typedef __future_base::_Result<_Res>& __result_type; | |
498 | ||
499 | private: | |
500 | __state_type _M_state; | |
501 | ||
c910ceff | 502 | public: |
c36abf03 BK |
503 | // Disable copying. |
504 | __basic_future(const __basic_future&) = delete; | |
505 | __basic_future& operator=(const __basic_future&) = delete; | |
c910ceff | 506 | |
c36abf03 | 507 | bool |
b3eed6fe | 508 | valid() const { return static_cast<bool>(_M_state); } |
c910ceff | 509 | |
c36abf03 | 510 | void |
5262c72a JW |
511 | wait() const |
512 | { | |
513 | _State::_S_check(_M_state); | |
514 | _M_state->wait(); | |
515 | } | |
c910ceff JW |
516 | |
517 | template<typename _Rep, typename _Period> | |
518 | bool | |
519 | wait_for(const chrono::duration<_Rep, _Period>& __rel) const | |
5262c72a JW |
520 | { |
521 | _State::_S_check(_M_state); | |
522 | return _M_state->wait_for(__rel); | |
523 | } | |
c910ceff JW |
524 | |
525 | template<typename _Clock, typename _Duration> | |
526 | bool | |
527 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) const | |
5262c72a JW |
528 | { |
529 | _State::_S_check(_M_state); | |
530 | return _M_state->wait_until(__abs); | |
531 | } | |
c910ceff JW |
532 | |
533 | protected: | |
c36abf03 BK |
534 | /// Wait for the state to be ready and rethrow any stored exception |
535 | __result_type | |
c910ceff JW |
536 | _M_get_result() |
537 | { | |
5262c72a | 538 | _State::_S_check(_M_state); |
b3eed6fe | 539 | _Result_base& __res = _M_state->wait(); |
c910ceff JW |
540 | if (!(__res._M_error == 0)) |
541 | rethrow_exception(__res._M_error); | |
c36abf03 | 542 | return static_cast<__result_type>(__res); |
c910ceff JW |
543 | } |
544 | ||
b3eed6fe JW |
545 | void _M_swap(__basic_future& __that) |
546 | { | |
547 | _M_state.swap(__that._M_state); | |
548 | } | |
549 | ||
550 | // Construction of a future by promise::get_future() | |
c910ceff | 551 | explicit |
c36abf03 | 552 | __basic_future(const __state_type& __state) : _M_state(__state) |
c910ceff | 553 | { |
b3eed6fe JW |
554 | _State::_S_check(_M_state); |
555 | _M_state->_M_set_retrieved_flag(); | |
c910ceff JW |
556 | } |
557 | ||
c36abf03 | 558 | // Copy construction from a shared_future |
c910ceff | 559 | explicit |
c36abf03 | 560 | __basic_future(const shared_future<_Res>&); |
c910ceff | 561 | |
b3eed6fe | 562 | // Move construction from a shared_future |
c910ceff | 563 | explicit |
b3eed6fe JW |
564 | __basic_future(shared_future<_Res>&&); |
565 | ||
566 | // Move construction from a future | |
567 | explicit | |
568 | __basic_future(future<_Res>&&); | |
569 | ||
85db9dcc | 570 | constexpr __basic_future() : _M_state() { } |
b3eed6fe JW |
571 | |
572 | struct _Reset | |
573 | { | |
574 | explicit _Reset(__basic_future& __fut) : _M_fut(__fut) { } | |
575 | ~_Reset() { _M_fut._M_state.reset(); } | |
576 | __basic_future& _M_fut; | |
577 | }; | |
c910ceff JW |
578 | }; |
579 | ||
c36abf03 | 580 | |
b3eed6fe | 581 | /// Primary template for future. |
c36abf03 | 582 | template<typename _Res> |
b3eed6fe | 583 | class future : public __basic_future<_Res> |
c910ceff | 584 | { |
c36abf03 | 585 | friend class promise<_Res>; |
b3eed6fe JW |
586 | template<typename> friend class packaged_task; |
587 | template<typename _Fn, typename... _Args> | |
73c5c5bb | 588 | friend future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe | 589 | async(launch, _Fn&&, _Args&&...); |
c36abf03 BK |
590 | |
591 | typedef __basic_future<_Res> _Base_type; | |
592 | typedef typename _Base_type::__state_type __state_type; | |
c36abf03 BK |
593 | |
594 | explicit | |
b3eed6fe | 595 | future(const __state_type& __state) : _Base_type(__state) { } |
c910ceff JW |
596 | |
597 | public: | |
85db9dcc | 598 | constexpr future() : _Base_type() { } |
b3eed6fe | 599 | |
c910ceff | 600 | /// Move constructor |
b3eed6fe | 601 | future(future&& __uf) : _Base_type(std::move(__uf)) { } |
c910ceff | 602 | |
c36abf03 | 603 | // Disable copying |
b3eed6fe JW |
604 | future(const future&) = delete; |
605 | future& operator=(const future&) = delete; | |
606 | ||
607 | future& operator=(future&& __fut) | |
608 | { | |
609 | future(std::move(__fut))._M_swap(*this); | |
610 | return *this; | |
611 | } | |
c910ceff | 612 | |
c36abf03 | 613 | /// Retrieving the value |
b3eed6fe | 614 | _Res |
c910ceff | 615 | get() |
b3eed6fe JW |
616 | { |
617 | typename _Base_type::_Reset __reset(*this); | |
618 | return std::move(this->_M_get_result()._M_value()); | |
619 | } | |
c910ceff JW |
620 | }; |
621 | ||
b3eed6fe | 622 | /// Partial specialization for future<R&> |
c36abf03 | 623 | template<typename _Res> |
b3eed6fe | 624 | class future<_Res&> : public __basic_future<_Res&> |
c910ceff | 625 | { |
c36abf03 | 626 | friend class promise<_Res&>; |
b3eed6fe JW |
627 | template<typename> friend class packaged_task; |
628 | template<typename _Fn, typename... _Args> | |
73c5c5bb | 629 | friend future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe | 630 | async(launch, _Fn&&, _Args&&...); |
c36abf03 BK |
631 | |
632 | typedef __basic_future<_Res&> _Base_type; | |
633 | typedef typename _Base_type::__state_type __state_type; | |
634 | ||
635 | explicit | |
b3eed6fe | 636 | future(const __state_type& __state) : _Base_type(__state) { } |
c36abf03 | 637 | |
c910ceff | 638 | public: |
85db9dcc | 639 | constexpr future() : _Base_type() { } |
b3eed6fe | 640 | |
c910ceff | 641 | /// Move constructor |
b3eed6fe | 642 | future(future&& __uf) : _Base_type(std::move(__uf)) { } |
c910ceff | 643 | |
c36abf03 | 644 | // Disable copying |
b3eed6fe JW |
645 | future(const future&) = delete; |
646 | future& operator=(const future&) = delete; | |
647 | ||
648 | future& operator=(future&& __fut) | |
649 | { | |
650 | future(std::move(__fut))._M_swap(*this); | |
651 | return *this; | |
652 | } | |
c910ceff | 653 | |
c36abf03 BK |
654 | /// Retrieving the value |
655 | _Res& | |
b3eed6fe JW |
656 | get() |
657 | { | |
658 | typename _Base_type::_Reset __reset(*this); | |
659 | return this->_M_get_result()._M_get(); | |
660 | } | |
c36abf03 | 661 | }; |
c910ceff | 662 | |
b3eed6fe | 663 | /// Explicit specialization for future<void> |
c36abf03 | 664 | template<> |
b3eed6fe | 665 | class future<void> : public __basic_future<void> |
c36abf03 BK |
666 | { |
667 | friend class promise<void>; | |
b3eed6fe JW |
668 | template<typename> friend class packaged_task; |
669 | template<typename _Fn, typename... _Args> | |
73c5c5bb | 670 | friend future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe | 671 | async(launch, _Fn&&, _Args&&...); |
c910ceff | 672 | |
c36abf03 BK |
673 | typedef __basic_future<void> _Base_type; |
674 | typedef typename _Base_type::__state_type __state_type; | |
c910ceff JW |
675 | |
676 | explicit | |
b3eed6fe | 677 | future(const __state_type& __state) : _Base_type(__state) { } |
c910ceff | 678 | |
c910ceff | 679 | public: |
85db9dcc | 680 | constexpr future() : _Base_type() { } |
b3eed6fe | 681 | |
c910ceff | 682 | /// Move constructor |
b3eed6fe | 683 | future(future&& __uf) : _Base_type(std::move(__uf)) { } |
c910ceff | 684 | |
c36abf03 | 685 | // Disable copying |
b3eed6fe JW |
686 | future(const future&) = delete; |
687 | future& operator=(const future&) = delete; | |
688 | ||
689 | future& operator=(future&& __fut) | |
690 | { | |
691 | future(std::move(__fut))._M_swap(*this); | |
692 | return *this; | |
693 | } | |
c910ceff | 694 | |
c36abf03 BK |
695 | /// Retrieving the value |
696 | void | |
b3eed6fe JW |
697 | get() |
698 | { | |
699 | typename _Base_type::_Reset __reset(*this); | |
700 | this->_M_get_result(); | |
701 | } | |
c910ceff JW |
702 | }; |
703 | ||
c36abf03 BK |
704 | |
705 | /// Primary template for shared_future. | |
706 | template<typename _Res> | |
707 | class shared_future : public __basic_future<_Res> | |
c910ceff | 708 | { |
c36abf03 BK |
709 | typedef __basic_future<_Res> _Base_type; |
710 | ||
c910ceff | 711 | public: |
85db9dcc | 712 | constexpr shared_future() : _Base_type() { } |
b3eed6fe | 713 | |
c910ceff JW |
714 | /// Copy constructor |
715 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
716 | ||
b3eed6fe JW |
717 | /// Construct from a future rvalue |
718 | shared_future(future<_Res>&& __uf) | |
c910ceff JW |
719 | : _Base_type(std::move(__uf)) |
720 | { } | |
721 | ||
b3eed6fe JW |
722 | /// Construct from a shared_future rvalue |
723 | shared_future(shared_future&& __sf) | |
724 | : _Base_type(std::move(__sf)) | |
725 | { } | |
726 | ||
727 | shared_future& operator=(const shared_future& __sf) | |
728 | { | |
729 | shared_future(__sf)._M_swap(*this); | |
730 | return *this; | |
731 | } | |
732 | ||
733 | shared_future& operator=(shared_future&& __sf) | |
734 | { | |
735 | shared_future(std::move(__sf))._M_swap(*this); | |
736 | return *this; | |
737 | } | |
c910ceff | 738 | |
c36abf03 BK |
739 | /// Retrieving the value |
740 | const _Res& | |
c910ceff | 741 | get() |
b3eed6fe | 742 | { |
c36abf03 BK |
743 | typename _Base_type::__result_type __r = this->_M_get_result(); |
744 | _Res& __rs(__r._M_value()); | |
745 | return __rs; | |
746 | } | |
c910ceff JW |
747 | }; |
748 | ||
c36abf03 BK |
749 | /// Partial specialization for shared_future<R&> |
750 | template<typename _Res> | |
751 | class shared_future<_Res&> : public __basic_future<_Res&> | |
c910ceff | 752 | { |
c36abf03 BK |
753 | typedef __basic_future<_Res&> _Base_type; |
754 | ||
c910ceff | 755 | public: |
85db9dcc | 756 | constexpr shared_future() : _Base_type() { } |
b3eed6fe | 757 | |
c910ceff JW |
758 | /// Copy constructor |
759 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
760 | ||
b3eed6fe JW |
761 | /// Construct from a future rvalue |
762 | shared_future(future<_Res&>&& __uf) | |
c910ceff JW |
763 | : _Base_type(std::move(__uf)) |
764 | { } | |
765 | ||
b3eed6fe JW |
766 | /// Construct from a shared_future rvalue |
767 | shared_future(shared_future&& __sf) | |
768 | : _Base_type(std::move(__sf)) | |
769 | { } | |
770 | ||
771 | shared_future& operator=(const shared_future& __sf) | |
772 | { | |
773 | shared_future(__sf)._M_swap(*this); | |
774 | return *this; | |
775 | } | |
776 | ||
777 | shared_future& operator=(shared_future&& __sf) | |
778 | { | |
779 | shared_future(std::move(__sf))._M_swap(*this); | |
780 | return *this; | |
781 | } | |
c910ceff | 782 | |
c36abf03 BK |
783 | /// Retrieving the value |
784 | _Res& | |
b3eed6fe | 785 | get() { return this->_M_get_result()._M_get(); } |
c910ceff JW |
786 | }; |
787 | ||
c36abf03 | 788 | /// Explicit specialization for shared_future<void> |
c910ceff | 789 | template<> |
c36abf03 | 790 | class shared_future<void> : public __basic_future<void> |
c910ceff | 791 | { |
c36abf03 BK |
792 | typedef __basic_future<void> _Base_type; |
793 | ||
c910ceff | 794 | public: |
85db9dcc | 795 | constexpr shared_future() : _Base_type() { } |
b3eed6fe | 796 | |
c910ceff JW |
797 | /// Copy constructor |
798 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
799 | ||
b3eed6fe JW |
800 | /// Construct from a future rvalue |
801 | shared_future(future<void>&& __uf) | |
c910ceff JW |
802 | : _Base_type(std::move(__uf)) |
803 | { } | |
804 | ||
b3eed6fe JW |
805 | /// Construct from a shared_future rvalue |
806 | shared_future(shared_future&& __sf) | |
807 | : _Base_type(std::move(__sf)) | |
808 | { } | |
809 | ||
810 | shared_future& operator=(const shared_future& __sf) | |
811 | { | |
812 | shared_future(__sf)._M_swap(*this); | |
813 | return *this; | |
814 | } | |
815 | ||
816 | shared_future& operator=(shared_future&& __sf) | |
817 | { | |
818 | shared_future(std::move(__sf))._M_swap(*this); | |
819 | return *this; | |
820 | } | |
c910ceff | 821 | |
c36abf03 BK |
822 | // Retrieving the value |
823 | void | |
824 | get() { this->_M_get_result(); } | |
c910ceff JW |
825 | }; |
826 | ||
c36abf03 BK |
827 | // Now we can define the protected __basic_future constructors. |
828 | template<typename _Res> | |
19501406 PC |
829 | inline __basic_future<_Res>:: |
830 | __basic_future(const shared_future<_Res>& __sf) | |
c910ceff JW |
831 | : _M_state(__sf._M_state) |
832 | { } | |
833 | ||
c36abf03 | 834 | template<typename _Res> |
19501406 PC |
835 | inline __basic_future<_Res>:: |
836 | __basic_future(shared_future<_Res>&& __sf) | |
b3eed6fe JW |
837 | : _M_state(std::move(__sf._M_state)) |
838 | { } | |
839 | ||
840 | template<typename _Res> | |
19501406 PC |
841 | inline __basic_future<_Res>:: |
842 | __basic_future(future<_Res>&& __uf) | |
c910ceff JW |
843 | : _M_state(std::move(__uf._M_state)) |
844 | { } | |
845 | ||
c36abf03 BK |
846 | |
847 | /// Primary template for promise | |
848 | template<typename _Res> | |
c910ceff JW |
849 | class promise |
850 | { | |
c36abf03 | 851 | typedef __future_base::_State _State; |
b3eed6fe JW |
852 | typedef __future_base::_Result<_Res> _Res_type; |
853 | typedef typename __future_base::_Ptr<_Res_type>::type _Ptr_type; | |
854 | template<typename, typename> friend class _State::_Setter; | |
c36abf03 BK |
855 | |
856 | shared_ptr<_State> _M_future; | |
b3eed6fe | 857 | _Ptr_type _M_storage; |
c36abf03 | 858 | |
c910ceff JW |
859 | public: |
860 | promise() | |
19501406 PC |
861 | : _M_future(std::make_shared<_State>()), |
862 | _M_storage(new _Res_type()) | |
c910ceff JW |
863 | { } |
864 | ||
865 | promise(promise&& __rhs) | |
866 | : _M_future(std::move(__rhs._M_future)), | |
19501406 | 867 | _M_storage(std::move(__rhs._M_storage)) |
c910ceff JW |
868 | { } |
869 | ||
c910ceff | 870 | template<typename _Allocator> |
b3eed6fe JW |
871 | promise(allocator_arg_t, const _Allocator& __a) |
872 | : _M_future(std::allocate_shared<_State>(__a)), | |
135a0d0a | 873 | _M_storage(__future_base::_S_allocate_result<_Res>(__a)) |
b3eed6fe | 874 | { } |
c910ceff JW |
875 | |
876 | promise(const promise&) = delete; | |
877 | ||
878 | ~promise() | |
879 | { | |
880 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
881 | _M_future->_M_break_promise(std::move(_M_storage)); | |
882 | } | |
883 | ||
c36abf03 | 884 | // Assignment |
c910ceff JW |
885 | promise& |
886 | operator=(promise&& __rhs) | |
887 | { | |
888 | promise(std::move(__rhs)).swap(*this); | |
889 | return *this; | |
890 | } | |
891 | ||
892 | promise& operator=(const promise&) = delete; | |
893 | ||
894 | void | |
895 | swap(promise& __rhs) | |
896 | { | |
897 | _M_future.swap(__rhs._M_future); | |
898 | _M_storage.swap(__rhs._M_storage); | |
899 | } | |
900 | ||
c36abf03 | 901 | // Retrieving the result |
b3eed6fe | 902 | future<_Res> |
c910ceff | 903 | get_future() |
b3eed6fe | 904 | { return future<_Res>(_M_future); } |
c910ceff | 905 | |
c36abf03 | 906 | // Setting the result |
c910ceff | 907 | void |
c36abf03 | 908 | set_value(const _Res& __r) |
c910ceff | 909 | { |
b3eed6fe JW |
910 | auto __setter = _State::__setter(this, __r); |
911 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff JW |
912 | } |
913 | ||
914 | void | |
c36abf03 | 915 | set_value(_Res&& __r) |
c910ceff | 916 | { |
b3eed6fe JW |
917 | auto __setter = _State::__setter(this, std::move(__r)); |
918 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff JW |
919 | } |
920 | ||
921 | void | |
922 | set_exception(exception_ptr __p) | |
923 | { | |
b3eed6fe JW |
924 | auto __setter = _State::__setter(__p, this); |
925 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff | 926 | } |
c910ceff JW |
927 | }; |
928 | ||
19501406 PC |
929 | template<typename _Res> |
930 | inline void | |
931 | swap(promise<_Res>& __x, promise<_Res>& __y) | |
932 | { __x.swap(__y); } | |
933 | ||
135a0d0a PC |
934 | template<typename _Res, typename _Alloc> |
935 | struct uses_allocator<promise<_Res>, _Alloc> | |
936 | : public true_type { }; | |
937 | ||
938 | ||
c36abf03 BK |
939 | /// Partial specialization for promise<R&> |
940 | template<typename _Res> | |
941 | class promise<_Res&> | |
c910ceff | 942 | { |
c36abf03 | 943 | typedef __future_base::_State _State; |
b3eed6fe JW |
944 | typedef __future_base::_Result<_Res&> _Res_type; |
945 | typedef typename __future_base::_Ptr<_Res_type>::type _Ptr_type; | |
946 | template<typename, typename> friend class _State::_Setter; | |
c36abf03 BK |
947 | |
948 | shared_ptr<_State> _M_future; | |
b3eed6fe | 949 | _Ptr_type _M_storage; |
c36abf03 | 950 | |
c910ceff JW |
951 | public: |
952 | promise() | |
19501406 PC |
953 | : _M_future(std::make_shared<_State>()), |
954 | _M_storage(new _Res_type()) | |
c910ceff JW |
955 | { } |
956 | ||
957 | promise(promise&& __rhs) | |
c36abf03 BK |
958 | : _M_future(std::move(__rhs._M_future)), |
959 | _M_storage(std::move(__rhs._M_storage)) | |
c910ceff JW |
960 | { } |
961 | ||
c910ceff | 962 | template<typename _Allocator> |
b3eed6fe JW |
963 | promise(allocator_arg_t, const _Allocator& __a) |
964 | : _M_future(std::allocate_shared<_State>(__a)), | |
135a0d0a | 965 | _M_storage(__future_base::_S_allocate_result<_Res&>(__a)) |
b3eed6fe | 966 | { } |
c910ceff JW |
967 | |
968 | promise(const promise&) = delete; | |
969 | ||
970 | ~promise() | |
971 | { | |
972 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
973 | _M_future->_M_break_promise(std::move(_M_storage)); | |
974 | } | |
975 | ||
c36abf03 | 976 | // Assignment |
c910ceff JW |
977 | promise& |
978 | operator=(promise&& __rhs) | |
979 | { | |
980 | promise(std::move(__rhs)).swap(*this); | |
981 | return *this; | |
982 | } | |
983 | ||
984 | promise& operator=(const promise&) = delete; | |
985 | ||
986 | void | |
987 | swap(promise& __rhs) | |
988 | { | |
989 | _M_future.swap(__rhs._M_future); | |
990 | _M_storage.swap(__rhs._M_storage); | |
991 | } | |
992 | ||
c36abf03 | 993 | // Retrieving the result |
b3eed6fe | 994 | future<_Res&> |
c910ceff | 995 | get_future() |
b3eed6fe | 996 | { return future<_Res&>(_M_future); } |
c910ceff | 997 | |
c36abf03 | 998 | // Setting the result |
c910ceff | 999 | void |
c36abf03 | 1000 | set_value(_Res& __r) |
c910ceff | 1001 | { |
b3eed6fe JW |
1002 | auto __setter = _State::__setter(this, __r); |
1003 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff JW |
1004 | } |
1005 | ||
1006 | void | |
1007 | set_exception(exception_ptr __p) | |
1008 | { | |
b3eed6fe JW |
1009 | auto __setter = _State::__setter(__p, this); |
1010 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff | 1011 | } |
c910ceff JW |
1012 | }; |
1013 | ||
c36abf03 | 1014 | /// Explicit specialization for promise<void> |
c910ceff JW |
1015 | template<> |
1016 | class promise<void> | |
1017 | { | |
c36abf03 | 1018 | typedef __future_base::_State _State; |
b3eed6fe JW |
1019 | typedef __future_base::_Result<void> _Res_type; |
1020 | typedef typename __future_base::_Ptr<_Res_type>::type _Ptr_type; | |
1021 | template<typename, typename> friend class _State::_Setter; | |
c36abf03 | 1022 | |
b3eed6fe JW |
1023 | shared_ptr<_State> _M_future; |
1024 | _Ptr_type _M_storage; | |
c36abf03 | 1025 | |
c910ceff JW |
1026 | public: |
1027 | promise() | |
c36abf03 | 1028 | : _M_future(std::make_shared<_State>()), |
b3eed6fe | 1029 | _M_storage(new _Res_type()) |
c910ceff JW |
1030 | { } |
1031 | ||
1032 | promise(promise&& __rhs) | |
1033 | : _M_future(std::move(__rhs._M_future)), | |
19501406 | 1034 | _M_storage(std::move(__rhs._M_storage)) |
c910ceff JW |
1035 | { } |
1036 | ||
c910ceff | 1037 | template<typename _Allocator> |
b3eed6fe JW |
1038 | promise(allocator_arg_t, const _Allocator& __a) |
1039 | : _M_future(std::allocate_shared<_State>(__a)), | |
135a0d0a | 1040 | _M_storage(__future_base::_S_allocate_result<void>(__a)) |
b3eed6fe | 1041 | { } |
c910ceff JW |
1042 | |
1043 | promise(const promise&) = delete; | |
1044 | ||
1045 | ~promise() | |
1046 | { | |
1047 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
1048 | _M_future->_M_break_promise(std::move(_M_storage)); | |
1049 | } | |
1050 | ||
c36abf03 | 1051 | // Assignment |
c910ceff JW |
1052 | promise& |
1053 | operator=(promise&& __rhs) | |
1054 | { | |
1055 | promise(std::move(__rhs)).swap(*this); | |
1056 | return *this; | |
1057 | } | |
1058 | ||
1059 | promise& operator=(const promise&) = delete; | |
1060 | ||
1061 | void | |
1062 | swap(promise& __rhs) | |
1063 | { | |
1064 | _M_future.swap(__rhs._M_future); | |
1065 | _M_storage.swap(__rhs._M_storage); | |
1066 | } | |
1067 | ||
c36abf03 | 1068 | // Retrieving the result |
b3eed6fe | 1069 | future<void> |
c910ceff | 1070 | get_future() |
b3eed6fe | 1071 | { return future<void>(_M_future); } |
c910ceff | 1072 | |
c36abf03 | 1073 | // Setting the result |
b3eed6fe JW |
1074 | void set_value(); |
1075 | ||
c910ceff | 1076 | void |
b3eed6fe | 1077 | set_exception(exception_ptr __p) |
c910ceff | 1078 | { |
b3eed6fe JW |
1079 | auto __setter = _State::__setter(__p, this); |
1080 | _M_future->_M_set_result(std::move(__setter)); | |
c910ceff | 1081 | } |
b3eed6fe | 1082 | }; |
c910ceff | 1083 | |
b3eed6fe JW |
1084 | // set void |
1085 | template<> | |
1086 | struct __future_base::_State::_Setter<void, void> | |
1087 | { | |
1088 | promise<void>::_Ptr_type operator()() | |
c910ceff | 1089 | { |
b3eed6fe JW |
1090 | _State::_S_check(_M_promise->_M_future); |
1091 | return std::move(_M_promise->_M_storage); | |
c910ceff JW |
1092 | } |
1093 | ||
b3eed6fe | 1094 | promise<void>* _M_promise; |
c910ceff JW |
1095 | }; |
1096 | ||
b3eed6fe JW |
1097 | inline __future_base::_State::_Setter<void, void> |
1098 | __future_base::_State::__setter(promise<void>* __prom) | |
1099 | { | |
1100 | return _Setter<void, void>{ __prom }; | |
1101 | } | |
1102 | ||
1103 | inline void | |
1104 | promise<void>::set_value() | |
1105 | { | |
1106 | auto __setter = _State::__setter(this); | |
1107 | _M_future->_M_set_result(std::move(__setter)); | |
1108 | } | |
1109 | ||
b3eed6fe JW |
1110 | |
1111 | template<typename _StateT, typename _Res> | |
1112 | struct __future_base::_Task_setter | |
c910ceff | 1113 | { |
b3eed6fe | 1114 | typename _StateT::_Ptr_type operator()() |
c910ceff | 1115 | { |
19501406 PC |
1116 | __try |
1117 | { | |
1118 | _M_state->_M_result->_M_set(_M_fn()); | |
1119 | } | |
1120 | __catch(...) | |
1121 | { | |
1122 | _M_state->_M_result->_M_error = current_exception(); | |
1123 | } | |
b3eed6fe | 1124 | return std::move(_M_state->_M_result); |
c910ceff | 1125 | } |
b3eed6fe JW |
1126 | _StateT* _M_state; |
1127 | std::function<_Res()> _M_fn; | |
c910ceff JW |
1128 | }; |
1129 | ||
b3eed6fe JW |
1130 | template<typename _StateT> |
1131 | struct __future_base::_Task_setter<_StateT, void> | |
c910ceff | 1132 | { |
b3eed6fe | 1133 | typename _StateT::_Ptr_type operator()() |
c910ceff | 1134 | { |
19501406 PC |
1135 | __try |
1136 | { | |
1137 | _M_fn(); | |
1138 | } | |
1139 | __catch(...) | |
1140 | { | |
1141 | _M_state->_M_result->_M_error = current_exception(); | |
1142 | } | |
1143 | return std::move(_M_state->_M_result); | |
c910ceff | 1144 | } |
b3eed6fe JW |
1145 | _StateT* _M_state; |
1146 | std::function<void()> _M_fn; | |
c910ceff JW |
1147 | }; |
1148 | ||
b3eed6fe JW |
1149 | template<typename _Res, typename... _Args> |
1150 | struct __future_base::_Task_state<_Res(_Args...)> : __future_base::_State | |
1151 | { | |
1152 | typedef _Res _Res_type; | |
1153 | ||
1154 | _Task_state(std::function<_Res(_Args...)> __task) | |
1155 | : _M_result(new _Result<_Res>()), _M_task(std::move(__task)) | |
1156 | { } | |
1157 | ||
b3eed6fe JW |
1158 | template<typename _Func, typename _Alloc> |
1159 | _Task_state(_Func&& __task, const _Alloc& __a) | |
135a0d0a PC |
1160 | : _M_result(_S_allocate_result<_Res>(__a)), |
1161 | _M_task(allocator_arg, __a, std::move(__task)) | |
b3eed6fe | 1162 | { } |
b3eed6fe JW |
1163 | |
1164 | void | |
1165 | _M_run(_Args... __args) | |
1166 | { | |
1167 | // bound arguments decay so wrap lvalue references | |
1b3fad81 | 1168 | auto __bound = std::bind<_Res>(std::ref(_M_task), |
b3eed6fe JW |
1169 | _S_maybe_wrap_ref(std::forward<_Args>(__args))...); |
1170 | _Task_setter<_Task_state> __setter{ this, std::move(__bound) }; | |
1171 | _M_set_result(std::move(__setter)); | |
1172 | } | |
1173 | ||
1174 | template<typename, typename> friend class _Task_setter; | |
1175 | typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type; | |
1176 | _Ptr_type _M_result; | |
1177 | std::function<_Res(_Args...)> _M_task; | |
1178 | ||
1179 | template<typename _Tp> | |
1180 | static reference_wrapper<_Tp> | |
1181 | _S_maybe_wrap_ref(_Tp& __t) | |
1182 | { return std::ref(__t); } | |
1183 | ||
1184 | template<typename _Tp> | |
1185 | static typename enable_if<!is_lvalue_reference<_Tp>::value, | |
1186 | _Tp>::type&& | |
1187 | _S_maybe_wrap_ref(_Tp&& __t) | |
1188 | { return std::forward<_Tp>(__t); } | |
1189 | }; | |
c36abf03 | 1190 | |
3259554a | 1191 | /// packaged_task |
c36abf03 BK |
1192 | template<typename _Res, typename... _ArgTypes> |
1193 | class packaged_task<_Res(_ArgTypes...)> | |
c910ceff | 1194 | { |
b3eed6fe JW |
1195 | typedef __future_base::_Task_state<_Res(_ArgTypes...)> _State_type; |
1196 | shared_ptr<_State_type> _M_state; | |
c36abf03 | 1197 | |
c910ceff | 1198 | public: |
c36abf03 | 1199 | typedef _Res result_type; |
c910ceff | 1200 | |
c36abf03 | 1201 | // Construction and destruction |
c910ceff JW |
1202 | packaged_task() { } |
1203 | ||
1204 | template<typename _Fn> | |
1205 | explicit | |
b3eed6fe JW |
1206 | packaged_task(const _Fn& __fn) |
1207 | : _M_state(std::make_shared<_State_type>(__fn)) | |
1208 | { } | |
c910ceff JW |
1209 | |
1210 | template<typename _Fn> | |
1211 | explicit | |
b3eed6fe JW |
1212 | packaged_task(_Fn&& __fn) |
1213 | : _M_state(std::make_shared<_State_type>(std::move(__fn))) | |
1214 | { } | |
c910ceff JW |
1215 | |
1216 | explicit | |
b3eed6fe JW |
1217 | packaged_task(_Res(*__fn)(_ArgTypes...)) |
1218 | : _M_state(std::make_shared<_State_type>(__fn)) | |
1219 | { } | |
c910ceff | 1220 | |
c910ceff JW |
1221 | template<typename _Fn, typename _Allocator> |
1222 | explicit | |
1223 | packaged_task(allocator_arg_t __tag, const _Allocator& __a, _Fn __fn) | |
b3eed6fe | 1224 | : _M_state(std::allocate_shared<_State_type>(__a, std::move(__fn))) |
c910ceff | 1225 | { } |
c910ceff | 1226 | |
b3eed6fe JW |
1227 | ~packaged_task() |
1228 | { | |
1229 | if (static_cast<bool>(_M_state) && !_M_state.unique()) | |
1230 | _M_state->_M_break_promise(std::move(_M_state->_M_result)); | |
1231 | } | |
c910ceff | 1232 | |
c36abf03 | 1233 | // No copy |
c910ceff JW |
1234 | packaged_task(packaged_task&) = delete; |
1235 | packaged_task& operator=(packaged_task&) = delete; | |
1236 | ||
c36abf03 | 1237 | // Move support |
c910ceff JW |
1238 | packaged_task(packaged_task&& __other) |
1239 | { this->swap(__other); } | |
1240 | ||
1241 | packaged_task& operator=(packaged_task&& __other) | |
1242 | { | |
1243 | packaged_task(std::move(__other)).swap(*this); | |
1244 | return *this; | |
1245 | } | |
1246 | ||
1247 | void | |
1248 | swap(packaged_task& __other) | |
b3eed6fe | 1249 | { _M_state.swap(__other._M_state); } |
c910ceff | 1250 | |
b3eed6fe | 1251 | explicit operator bool() const { return static_cast<bool>(_M_state); } |
c910ceff | 1252 | |
c36abf03 | 1253 | // Result retrieval |
b3eed6fe | 1254 | future<_Res> |
c910ceff | 1255 | get_future() |
b3eed6fe | 1256 | { return future<_Res>(_M_state); } |
c910ceff | 1257 | |
c36abf03 | 1258 | // Execution |
c910ceff JW |
1259 | void |
1260 | operator()(_ArgTypes... __args) | |
1261 | { | |
b3eed6fe JW |
1262 | __future_base::_State::_S_check(_M_state); |
1263 | _M_state->_M_run(std::forward<_ArgTypes>(__args)...); | |
1264 | } | |
8d1b99e2 | 1265 | |
b3eed6fe JW |
1266 | void |
1267 | reset() | |
1268 | { | |
1269 | __future_base::_State::_S_check(_M_state); | |
1270 | packaged_task(std::move(_M_state->_M_task)).swap(*this); | |
1271 | } | |
1272 | }; | |
1273 | ||
94a86be0 | 1274 | /// swap |
19501406 | 1275 | template<typename _Res, typename... _ArgTypes> |
4e4d27aa | 1276 | inline void |
19501406 PC |
1277 | swap(packaged_task<_Res(_ArgTypes...)>& __x, |
1278 | packaged_task<_Res(_ArgTypes...)>& __y) | |
1279 | { __x.swap(__y); } | |
135a0d0a PC |
1280 | |
1281 | template<typename _Res, typename _Alloc> | |
1282 | struct uses_allocator<packaged_task<_Res>, _Alloc> | |
1283 | : public true_type { }; | |
1284 | ||
1285 | ||
b3eed6fe JW |
1286 | template<typename _Res> |
1287 | class __future_base::_Deferred_state : public __future_base::_State | |
1288 | { | |
1289 | public: | |
1290 | typedef _Res _Res_type; | |
1291 | ||
1292 | explicit | |
1293 | _Deferred_state(std::function<_Res()>&& __fn) | |
1294 | : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)) | |
1295 | { } | |
1296 | ||
1297 | private: | |
1298 | template<typename, typename> friend class _Task_setter; | |
1299 | typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type; | |
1300 | _Ptr_type _M_result; | |
1301 | std::function<_Res()> _M_fn; | |
1302 | ||
1303 | virtual void | |
1304 | _M_run_deferred() | |
1305 | { | |
1306 | _Task_setter<_Deferred_state> __setter{ this, _M_fn }; | |
1307 | // safe to call multiple times so ignore failure | |
1308 | _M_set_result(std::move(__setter), true); | |
1309 | } | |
1310 | }; | |
1311 | ||
1312 | template<typename _Res> | |
1313 | class __future_base::_Async_state : public __future_base::_State | |
1314 | { | |
1315 | public: | |
1316 | typedef _Res _Res_type; | |
1317 | ||
1318 | explicit | |
1319 | _Async_state(std::function<_Res()>&& __fn) | |
1320 | : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)), | |
19501406 | 1321 | _M_thread(mem_fn(&_Async_state::_M_do_run), this) |
b3eed6fe JW |
1322 | { } |
1323 | ||
1324 | ~_Async_state() { _M_thread.join(); } | |
1325 | ||
1326 | private: | |
1327 | void _M_do_run() | |
1328 | { | |
1329 | _Task_setter<_Async_state> __setter{ this, std::move(_M_fn) }; | |
1330 | _M_set_result(std::move(__setter)); | |
c910ceff JW |
1331 | } |
1332 | ||
b3eed6fe JW |
1333 | template<typename, typename> friend class _Task_setter; |
1334 | typedef typename __future_base::_Ptr<_Result<_Res>>::type _Ptr_type; | |
1335 | _Ptr_type _M_result; | |
1336 | std::function<_Res()> _M_fn; | |
1337 | thread _M_thread; | |
c910ceff JW |
1338 | }; |
1339 | ||
94a86be0 | 1340 | /// async |
b3eed6fe | 1341 | template<typename _Fn, typename... _Args> |
73c5c5bb | 1342 | future<typename result_of<_Fn(_Args...)>::type> |
b3eed6fe JW |
1343 | async(launch __policy, _Fn&& __fn, _Args&&... __args) |
1344 | { | |
73c5c5bb | 1345 | typedef typename result_of<_Fn(_Args...)>::type result_type; |
b3eed6fe JW |
1346 | std::shared_ptr<__future_base::_State> __state; |
1347 | if (__policy == launch::async) | |
19501406 PC |
1348 | { |
1349 | typedef typename __future_base::_Async_state<result_type> _State; | |
1350 | __state = std::make_shared<_State>(std::bind<result_type>( | |
b3eed6fe | 1351 | std::forward<_Fn>(__fn), std::forward<_Args>(__args)...)); |
19501406 | 1352 | } |
b3eed6fe | 1353 | else |
19501406 PC |
1354 | { |
1355 | typedef typename __future_base::_Deferred_state<result_type> _State; | |
1356 | __state = std::make_shared<_State>(std::bind<result_type>( | |
b3eed6fe | 1357 | std::forward<_Fn>(__fn), std::forward<_Args>(__args)...)); |
19501406 | 1358 | } |
b3eed6fe JW |
1359 | return future<result_type>(__state); |
1360 | } | |
1361 | ||
94a86be0 | 1362 | /// async, potential overload |
b3eed6fe | 1363 | template<typename _Fn, typename... _Args> |
73c5c5bb JW |
1364 | inline typename |
1365 | enable_if<!is_same<typename decay<_Fn>::type, launch>::value, | |
1366 | future<decltype(std::declval<_Fn>()(std::declval<_Args>()...))> | |
1367 | >::type | |
b3eed6fe JW |
1368 | async(_Fn&& __fn, _Args&&... __args) |
1369 | { | |
1370 | return async(launch::any, std::forward<_Fn>(__fn), | |
19501406 | 1371 | std::forward<_Args>(__args)...); |
b3eed6fe JW |
1372 | } |
1373 | ||
c910ceff JW |
1374 | #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 |
1375 | // && _GLIBCXX_ATOMIC_BUILTINS_4 | |
1376 | ||
41ca4246 | 1377 | // @} group futures |
53dc5044 | 1378 | _GLIBCXX_END_NAMESPACE |
41ca4246 | 1379 | |
c910ceff JW |
1380 | #endif // __GXX_EXPERIMENTAL_CXX0X__ |
1381 | ||
1382 | #endif // _GLIBCXX_FUTURE |