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