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