]>
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> | |
41 | #include <condition_variable> | |
42 | #include <system_error> | |
43 | #include <exception> | |
44 | #include <cstdatomic> | |
45 | ||
c910ceff JW |
46 | namespace std |
47 | { | |
48 | /** | |
49 | * @defgroup futures Futures | |
50 | * @ingroup concurrency | |
51 | * | |
52 | * Classes for futures support. | |
53 | * @{ | |
54 | */ | |
55 | ||
56 | /// Error code for futures | |
57 | enum class future_errc | |
58 | { broken_promise, future_already_retrieved, promise_already_satisfied }; | |
59 | ||
60 | // TODO: requires concepts | |
61 | // concept_map ErrorCodeEnum<future_errc> { } | |
62 | template<> | |
63 | struct is_error_code_enum<future_errc> : public true_type { }; | |
64 | ||
65 | /// Points to a statically-allocated object derived from error_category. | |
66 | extern const error_category* const future_category; | |
67 | ||
68 | // TODO: requires constexpr | |
69 | inline error_code make_error_code(future_errc __errc) | |
70 | { return error_code(static_cast<int>(__errc), *future_category); } | |
71 | ||
72 | // TODO: requires constexpr | |
73 | inline error_condition make_error_condition(future_errc __errc) | |
74 | { return error_condition(static_cast<int>(__errc), *future_category); } | |
75 | ||
8d1b99e2 BK |
76 | /** |
77 | * @brief Exception type thrown by futures. | |
78 | * @ingroup exceptions | |
79 | */ | |
c910ceff JW |
80 | class future_error : public logic_error |
81 | { | |
c36abf03 | 82 | error_code _M_code; |
8d1b99e2 | 83 | |
c910ceff JW |
84 | public: |
85 | explicit future_error(future_errc __ec) | |
86 | : logic_error("std::future_error"), _M_code(make_error_code(__ec)) | |
87 | { } | |
88 | ||
8d1b99e2 | 89 | virtual ~future_error() throw(); |
c910ceff | 90 | |
8d1b99e2 BK |
91 | virtual const char* |
92 | what() const throw(); | |
c910ceff | 93 | |
8d1b99e2 BK |
94 | const error_code& |
95 | code() const throw() { return _M_code; } | |
c910ceff JW |
96 | }; |
97 | ||
3259554a | 98 | // Forward declarations. |
c36abf03 | 99 | template<typename _Res> |
3259554a BK |
100 | class unique_future; |
101 | ||
c36abf03 | 102 | template<typename _Res> |
3259554a BK |
103 | class shared_future; |
104 | ||
105 | template<typename> | |
106 | class packaged_task; | |
107 | ||
c36abf03 | 108 | template<typename _Res> |
3259554a BK |
109 | class promise; |
110 | ||
41ca4246 BK |
111 | #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \ |
112 | && defined(_GLIBCXX_ATOMIC_BUILTINS_4) | |
113 | ||
c36abf03 BK |
114 | /// Base class and enclosing scope. |
115 | struct __future_base | |
c910ceff | 116 | { |
c36abf03 BK |
117 | /// Base class for results. |
118 | struct _Result_base | |
119 | { | |
120 | exception_ptr _M_error; | |
c910ceff | 121 | |
c36abf03 BK |
122 | _Result_base() = default; |
123 | _Result_base(const _Result_base&) = delete; | |
124 | _Result_base& operator=(const _Result_base&) = delete; | |
c910ceff | 125 | |
c36abf03 BK |
126 | // _M_destroy() allows derived classes to control deallocation, |
127 | // which will be needed when allocator support is added to promise. | |
128 | // See http://gcc.gnu.org/ml/libstdc++/2009-06/msg00032.html | |
129 | virtual void _M_destroy() = 0; | |
c910ceff | 130 | |
c36abf03 BK |
131 | struct _Deleter |
132 | { | |
133 | void operator()(_Result_base* __fr) const { __fr->_M_destroy(); } | |
134 | }; | |
c910ceff | 135 | |
c36abf03 BK |
136 | protected: |
137 | ~_Result_base(); | |
138 | }; | |
20f2653e | 139 | |
c36abf03 BK |
140 | /// Result. |
141 | template<typename _Res> | |
142 | struct _Result : _Result_base | |
143 | { | |
144 | private: | |
145 | typedef alignment_of<_Res> __a_of; | |
146 | typedef aligned_storage<sizeof(_Res), __a_of::value> __align_storage; | |
147 | typedef typename __align_storage::type __align_type; | |
148 | ||
149 | __align_type _M_storage; | |
150 | bool _M_initialized; | |
151 | ||
152 | public: | |
153 | _Result() : _M_initialized() { } | |
154 | ||
155 | ~_Result() | |
156 | { | |
157 | if (_M_initialized) | |
158 | _M_value().~_Res(); | |
159 | } | |
160 | ||
161 | // Return lvalue, future will add const or rvalue-reference | |
162 | _Res& | |
163 | _M_value() { return *static_cast<_Res*>(_M_addr()); } | |
164 | ||
165 | void | |
166 | _M_set(const _Res& __res) | |
167 | { | |
168 | ::new (_M_addr()) _Res(__res); | |
169 | _M_initialized = true; | |
170 | } | |
171 | ||
172 | void | |
173 | _M_set(_Res&& __res) | |
174 | { | |
175 | ::new (_M_addr()) _Res(_Move_result<_Res>::_S_move(__res)); | |
176 | _M_initialized = true; | |
177 | } | |
178 | ||
179 | private: | |
180 | void _M_destroy() { delete this; } | |
181 | ||
182 | void* _M_addr() { return static_cast<void*>(&_M_storage); } | |
c910ceff JW |
183 | }; |
184 | ||
c910ceff | 185 | |
c36abf03 BK |
186 | /// Workaround for CWG issue 664 and c++/34022 |
187 | template<typename _Res, bool = is_scalar<_Res>::value> | |
188 | struct _Move_result; | |
c910ceff | 189 | |
c36abf03 BK |
190 | /// Specialization for scalar types returns rvalue not rvalue-reference. |
191 | template<typename _Res> | |
192 | struct _Move_result<_Res, true> | |
193 | { | |
194 | typedef _Res __rval_type; | |
195 | static _Res _S_move(_Res __res) { return __res; } | |
196 | }; | |
197 | ||
198 | /// Specialization for non-scalar types returns rvalue-reference. | |
199 | template<typename _Res> | |
200 | struct _Move_result<_Res, false> | |
201 | { | |
202 | typedef _Res&& __rval_type; | |
203 | static _Res&& _S_move(_Res& __res) { return std::move(__res); } | |
204 | }; | |
205 | ||
206 | ||
207 | // TODO: use template alias when available | |
208 | /* | |
209 | template<typename _Res> | |
210 | using _Ptr = unique_ptr<_Res, _Result_base::_Deleter>; | |
211 | */ | |
212 | /// A unique_ptr based on the instantiating type. | |
213 | template<typename _Res> | |
214 | struct _Ptr | |
215 | { | |
216 | typedef unique_ptr<_Res, _Result_base::_Deleter> type; | |
217 | }; | |
c910ceff | 218 | |
c910ceff | 219 | |
c36abf03 BK |
220 | /// Shared state between a promise and one or more associated futures. |
221 | class _State | |
c910ceff | 222 | { |
c36abf03 | 223 | typedef _Ptr<_Result_base>::type _Ptr_type; |
c910ceff | 224 | |
c36abf03 BK |
225 | _Ptr_type _M_result; |
226 | mutex _M_mutex; | |
227 | condition_variable _M_cond; | |
228 | atomic_flag _M_retrieved; | |
c910ceff | 229 | |
c36abf03 BK |
230 | public: |
231 | _State() : _M_result(), _M_retrieved(ATOMIC_FLAG_INIT) { } | |
232 | ||
233 | _State(const _State&) = delete; | |
234 | _State& operator=(const _State&) = delete; | |
c910ceff | 235 | |
c910ceff | 236 | bool |
c36abf03 BK |
237 | is_ready() |
238 | { return _M_get() != 0; } | |
c910ceff | 239 | |
c910ceff | 240 | bool |
c36abf03 | 241 | has_exception() |
c910ceff | 242 | { |
c36abf03 BK |
243 | _Result_base* const __res = _M_get(); |
244 | return __res && !(__res->_M_error == 0); | |
c910ceff JW |
245 | } |
246 | ||
c36abf03 BK |
247 | bool |
248 | has_value() | |
c910ceff | 249 | { |
c36abf03 BK |
250 | _Result_base* const __res = _M_get(); |
251 | return __res && (__res->_M_error == 0); | |
c910ceff | 252 | } |
c910ceff | 253 | |
c36abf03 BK |
254 | _Result_base& |
255 | wait() | |
c910ceff | 256 | { |
c36abf03 BK |
257 | unique_lock<mutex> __lock(_M_mutex); |
258 | if (!_M_ready()) | |
259 | _M_cond.wait(__lock, std::bind(&_State::_M_ready, this)); | |
260 | return *_M_result; | |
c910ceff | 261 | } |
c910ceff | 262 | |
c36abf03 BK |
263 | template<typename _Rep, typename _Period> |
264 | bool | |
265 | wait_for(const chrono::duration<_Rep, _Period>& __rel) | |
266 | { | |
267 | unique_lock<mutex> __lock(_M_mutex); | |
268 | auto __bound = std::bind(&_State::_M_ready, this); | |
269 | return _M_ready() || _M_cond.wait_for(__lock, __rel, __bound); | |
270 | } | |
c910ceff | 271 | |
c36abf03 BK |
272 | template<typename _Clock, typename _Duration> |
273 | bool | |
274 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) | |
275 | { | |
276 | unique_lock<mutex> __lock(_M_mutex); | |
277 | auto __bound = std::bind(&_State::_M_ready, this); | |
278 | return _M_ready() || _M_cond.wait_until(__lock, __abs, __bound); | |
279 | } | |
c910ceff | 280 | |
c36abf03 BK |
281 | void |
282 | _M_set_result(_Ptr_type __res) | |
c910ceff | 283 | { |
c36abf03 BK |
284 | { |
285 | lock_guard<mutex> __lock(_M_mutex); | |
286 | if (_M_ready()) | |
287 | __throw_future_error(int(future_errc::promise_already_satisfied)); | |
288 | _M_result.swap(__res); | |
289 | } | |
290 | _M_cond.notify_all(); | |
c910ceff JW |
291 | } |
292 | ||
c910ceff | 293 | void |
c36abf03 | 294 | _M_break_promise(_Ptr_type __res) |
c910ceff | 295 | { |
c36abf03 BK |
296 | if (static_cast<bool>(__res)) |
297 | { | |
298 | future_errc __ec(future_errc::broken_promise); // XXX | |
299 | __res->_M_error = copy_exception(future_error(__ec)); | |
300 | { | |
301 | lock_guard<mutex> __lock(_M_mutex); | |
302 | _M_result.swap(__res); | |
303 | } | |
304 | _M_cond.notify_all(); | |
305 | } | |
c910ceff JW |
306 | } |
307 | ||
c36abf03 | 308 | // Called when this object is passed to a unique_future. |
c910ceff | 309 | void |
c36abf03 | 310 | _M_set_retrieved_flag() |
c910ceff | 311 | { |
c36abf03 BK |
312 | if (_M_retrieved.test_and_set()) |
313 | __throw_future_error(int(future_errc::future_already_retrieved)); | |
c910ceff JW |
314 | } |
315 | ||
316 | private: | |
c36abf03 BK |
317 | _Result_base* |
318 | _M_get() | |
319 | { | |
320 | lock_guard<mutex> __lock(_M_mutex); | |
321 | return _M_result.get(); | |
322 | } | |
c910ceff | 323 | |
c36abf03 | 324 | bool _M_ready() const { return static_cast<bool>(_M_result); } |
c910ceff | 325 | }; |
c36abf03 | 326 | }; |
c910ceff | 327 | |
c36abf03 | 328 | inline __future_base::_Result_base::~_Result_base() = default; |
c910ceff | 329 | |
c36abf03 BK |
330 | /// Partial specialization for reference types. |
331 | template<typename _Res> | |
332 | struct __future_base::_Result<_Res&> : __future_base::_Result_base | |
333 | { | |
334 | _Result() : _M_value_ptr() { } | |
c910ceff | 335 | |
c36abf03 BK |
336 | _Res* _M_value_ptr; |
337 | ||
338 | private: | |
c910ceff JW |
339 | void _M_destroy() { delete this; } |
340 | }; | |
341 | ||
c36abf03 | 342 | /// Explicit specialization for void. |
c910ceff | 343 | template<> |
c36abf03 | 344 | struct __future_base::_Result<void> : __future_base::_Result_base |
c910ceff | 345 | { |
c36abf03 | 346 | private: |
c910ceff JW |
347 | void _M_destroy() { delete this; } |
348 | }; | |
349 | ||
c36abf03 BK |
350 | |
351 | /// Common implementation for unique_future and shared_future. | |
352 | template<typename _Res> | |
353 | class __basic_future : public __future_base | |
c910ceff | 354 | { |
c36abf03 BK |
355 | protected: |
356 | typedef shared_ptr<_State> __state_type; | |
357 | typedef __future_base::_Result<_Res>& __result_type; | |
358 | ||
359 | private: | |
360 | __state_type _M_state; | |
361 | ||
c910ceff | 362 | public: |
c36abf03 BK |
363 | // Disable copying. |
364 | __basic_future(const __basic_future&) = delete; | |
365 | __basic_future& operator=(const __basic_future&) = delete; | |
c910ceff | 366 | |
c36abf03 BK |
367 | // Functions to check state and wait for ready. |
368 | bool | |
369 | is_ready() const { return this->_M_state->is_ready(); } | |
c910ceff | 370 | |
c36abf03 BK |
371 | bool |
372 | has_exception() const { return this->_M_state->has_exception(); } | |
c910ceff | 373 | |
c36abf03 BK |
374 | bool |
375 | has_value() const { return this->_M_state->has_value(); } | |
c910ceff | 376 | |
c36abf03 BK |
377 | void |
378 | wait() const { this->_M_state->wait(); } | |
c910ceff JW |
379 | |
380 | template<typename _Rep, typename _Period> | |
381 | bool | |
382 | wait_for(const chrono::duration<_Rep, _Period>& __rel) const | |
383 | { return this->_M_state->wait_for(__rel); } | |
384 | ||
385 | template<typename _Clock, typename _Duration> | |
386 | bool | |
387 | wait_until(const chrono::time_point<_Clock, _Duration>& __abs) const | |
388 | { return this->_M_state->wait_until(__abs); } | |
389 | ||
390 | protected: | |
c36abf03 BK |
391 | /// Wait for the state to be ready and rethrow any stored exception |
392 | __result_type | |
c910ceff JW |
393 | _M_get_result() |
394 | { | |
c36abf03 | 395 | _Result_base& __res = this->_M_state->wait(); |
c910ceff JW |
396 | if (!(__res._M_error == 0)) |
397 | rethrow_exception(__res._M_error); | |
c36abf03 | 398 | return static_cast<__result_type>(__res); |
c910ceff JW |
399 | } |
400 | ||
c36abf03 | 401 | // Construction of a unique_future by promise::get_future() |
c910ceff | 402 | explicit |
c36abf03 | 403 | __basic_future(const __state_type& __state) : _M_state(__state) |
c910ceff JW |
404 | { |
405 | if (static_cast<bool>(this->_M_state)) | |
406 | this->_M_state->_M_set_retrieved_flag(); | |
407 | else | |
8d1b99e2 | 408 | __throw_future_error(int(future_errc::future_already_retrieved)); |
c910ceff JW |
409 | } |
410 | ||
c36abf03 | 411 | // Copy construction from a shared_future |
c910ceff | 412 | explicit |
c36abf03 | 413 | __basic_future(const shared_future<_Res>&); |
c910ceff | 414 | |
c36abf03 | 415 | // Move construction from a unique_future |
c910ceff | 416 | explicit |
c36abf03 | 417 | __basic_future(unique_future<_Res>&&); |
c910ceff JW |
418 | }; |
419 | ||
c36abf03 BK |
420 | |
421 | /// Primary template for unique_future. | |
422 | template<typename _Res> | |
423 | class unique_future : public __basic_future<_Res> | |
c910ceff | 424 | { |
c36abf03 BK |
425 | friend class promise<_Res>; |
426 | ||
427 | typedef __basic_future<_Res> _Base_type; | |
428 | typedef typename _Base_type::__state_type __state_type; | |
429 | typedef __future_base::_Move_result<_Res> _Mover; | |
430 | ||
431 | explicit | |
432 | unique_future(const __state_type& __state) : _Base_type(__state) { } | |
c910ceff JW |
433 | |
434 | public: | |
435 | /// Move constructor | |
436 | unique_future(unique_future&& __uf) : _Base_type(std::move(__uf)) { } | |
437 | ||
c36abf03 | 438 | // Disable copying |
c910ceff JW |
439 | unique_future(const unique_future&) = delete; |
440 | unique_future& operator=(const unique_future&) = delete; | |
441 | ||
c36abf03 | 442 | /// Retrieving the value |
c910ceff JW |
443 | typename _Mover::__rval_type |
444 | get() | |
445 | { return _Mover::_S_move(this->_M_get_result()._M_value()); } | |
c910ceff JW |
446 | }; |
447 | ||
c36abf03 BK |
448 | /// Partial specialization for unique_future<R&> |
449 | template<typename _Res> | |
450 | class unique_future<_Res&> : public __basic_future<_Res&> | |
c910ceff | 451 | { |
c36abf03 BK |
452 | friend class promise<_Res&>; |
453 | ||
454 | typedef __basic_future<_Res&> _Base_type; | |
455 | typedef typename _Base_type::__state_type __state_type; | |
456 | ||
457 | explicit | |
458 | unique_future(const __state_type& __state) : _Base_type(__state) { } | |
459 | ||
c910ceff JW |
460 | public: |
461 | /// Move constructor | |
462 | unique_future(unique_future&& __uf) : _Base_type(std::move(__uf)) { } | |
463 | ||
c36abf03 | 464 | // Disable copying |
c910ceff JW |
465 | unique_future(const unique_future&) = delete; |
466 | unique_future& operator=(const unique_future&) = delete; | |
467 | ||
c36abf03 BK |
468 | /// Retrieving the value |
469 | _Res& | |
470 | get() { return *this->_M_get_result()._M_value_ptr; } | |
471 | }; | |
c910ceff | 472 | |
c36abf03 BK |
473 | /// Explicit specialization for unique_future<void> |
474 | template<> | |
475 | class unique_future<void> : public __basic_future<void> | |
476 | { | |
477 | friend class promise<void>; | |
c910ceff | 478 | |
c36abf03 BK |
479 | typedef __basic_future<void> _Base_type; |
480 | typedef typename _Base_type::__state_type __state_type; | |
c910ceff JW |
481 | |
482 | explicit | |
c36abf03 | 483 | unique_future(const __state_type& __state) : _Base_type(__state) { } |
c910ceff | 484 | |
c910ceff JW |
485 | public: |
486 | /// Move constructor | |
487 | unique_future(unique_future&& __uf) : _Base_type(std::move(__uf)) { } | |
488 | ||
c36abf03 | 489 | // Disable copying |
c910ceff JW |
490 | unique_future(const unique_future&) = delete; |
491 | unique_future& operator=(const unique_future&) = delete; | |
492 | ||
c36abf03 BK |
493 | /// Retrieving the value |
494 | void | |
495 | get() { this->_M_get_result(); } | |
c910ceff JW |
496 | }; |
497 | ||
c36abf03 BK |
498 | |
499 | /// Primary template for shared_future. | |
500 | template<typename _Res> | |
501 | class shared_future : public __basic_future<_Res> | |
c910ceff | 502 | { |
c36abf03 BK |
503 | typedef __basic_future<_Res> _Base_type; |
504 | ||
c910ceff JW |
505 | public: |
506 | /// Copy constructor | |
507 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
508 | ||
509 | /// Construct from a unique_future rvalue | |
c36abf03 | 510 | shared_future(unique_future<_Res>&& __uf) |
c910ceff JW |
511 | : _Base_type(std::move(__uf)) |
512 | { } | |
513 | ||
514 | shared_future& operator=(const shared_future&) = delete; | |
515 | ||
c36abf03 BK |
516 | /// Retrieving the value |
517 | const _Res& | |
c910ceff | 518 | get() |
c36abf03 BK |
519 | { |
520 | typename _Base_type::__result_type __r = this->_M_get_result(); | |
521 | _Res& __rs(__r._M_value()); | |
522 | return __rs; | |
523 | } | |
c910ceff JW |
524 | }; |
525 | ||
c36abf03 BK |
526 | /// Partial specialization for shared_future<R&> |
527 | template<typename _Res> | |
528 | class shared_future<_Res&> : public __basic_future<_Res&> | |
c910ceff | 529 | { |
c36abf03 BK |
530 | typedef __basic_future<_Res&> _Base_type; |
531 | ||
c910ceff JW |
532 | public: |
533 | /// Copy constructor | |
534 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
535 | ||
536 | /// Construct from a unique_future rvalue | |
c36abf03 | 537 | shared_future(unique_future<_Res&>&& __uf) |
c910ceff JW |
538 | : _Base_type(std::move(__uf)) |
539 | { } | |
540 | ||
541 | shared_future& operator=(const shared_future&) = delete; | |
542 | ||
c36abf03 BK |
543 | /// Retrieving the value |
544 | _Res& | |
545 | get() { return *this->_M_get_result()._M_value_ptr; } | |
c910ceff JW |
546 | }; |
547 | ||
c36abf03 | 548 | /// Explicit specialization for shared_future<void> |
c910ceff | 549 | template<> |
c36abf03 | 550 | class shared_future<void> : public __basic_future<void> |
c910ceff | 551 | { |
c36abf03 BK |
552 | typedef __basic_future<void> _Base_type; |
553 | ||
c910ceff JW |
554 | public: |
555 | /// Copy constructor | |
556 | shared_future(const shared_future& __sf) : _Base_type(__sf) { } | |
557 | ||
558 | /// Construct from a unique_future rvalue | |
559 | shared_future(unique_future<void>&& __uf) | |
560 | : _Base_type(std::move(__uf)) | |
561 | { } | |
562 | ||
563 | shared_future& operator=(const shared_future&) = delete; | |
564 | ||
c36abf03 BK |
565 | // Retrieving the value |
566 | void | |
567 | get() { this->_M_get_result(); } | |
c910ceff JW |
568 | }; |
569 | ||
c36abf03 BK |
570 | // Now we can define the protected __basic_future constructors. |
571 | template<typename _Res> | |
572 | __basic_future<_Res>::__basic_future(const shared_future<_Res>& __sf) | |
c910ceff JW |
573 | : _M_state(__sf._M_state) |
574 | { } | |
575 | ||
c36abf03 BK |
576 | template<typename _Res> |
577 | __basic_future<_Res>::__basic_future(unique_future<_Res>&& __uf) | |
c910ceff JW |
578 | : _M_state(std::move(__uf._M_state)) |
579 | { } | |
580 | ||
c36abf03 BK |
581 | |
582 | /// Primary template for promise | |
583 | template<typename _Res> | |
c910ceff JW |
584 | class promise |
585 | { | |
c36abf03 BK |
586 | template<typename> friend class packaged_task; |
587 | ||
588 | typedef __future_base::_State _State; | |
589 | typedef __future_base::_Move_result<_Res> _Mover; | |
590 | typedef __future_base::_Result<_Res> result_type; | |
591 | ||
592 | shared_ptr<_State> _M_future; | |
593 | typename __future_base::_Ptr<result_type>::type _M_storage; | |
594 | ||
c910ceff JW |
595 | public: |
596 | promise() | |
c36abf03 | 597 | : _M_future(std::make_shared<_State>()), _M_storage(new result_type()) |
c910ceff JW |
598 | { } |
599 | ||
600 | promise(promise&& __rhs) | |
601 | : _M_future(std::move(__rhs._M_future)), | |
602 | _M_storage(std::move(__rhs._M_storage)) | |
603 | { } | |
604 | ||
605 | // TODO: requires allocator concepts | |
606 | /* | |
607 | template<typename _Allocator> | |
608 | promise(allocator_arg_t, const _Allocator& __a); | |
609 | ||
610 | template<typename _Allocator> | |
611 | promise(allocator_arg_t, const _Allocator&, promise&& __rhs); | |
612 | */ | |
613 | ||
614 | promise(const promise&) = delete; | |
615 | ||
616 | ~promise() | |
617 | { | |
618 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
619 | _M_future->_M_break_promise(std::move(_M_storage)); | |
620 | } | |
621 | ||
c36abf03 | 622 | // Assignment |
c910ceff JW |
623 | promise& |
624 | operator=(promise&& __rhs) | |
625 | { | |
626 | promise(std::move(__rhs)).swap(*this); | |
627 | return *this; | |
628 | } | |
629 | ||
630 | promise& operator=(const promise&) = delete; | |
631 | ||
632 | void | |
633 | swap(promise& __rhs) | |
634 | { | |
635 | _M_future.swap(__rhs._M_future); | |
636 | _M_storage.swap(__rhs._M_storage); | |
637 | } | |
638 | ||
c36abf03 BK |
639 | // Retrieving the result |
640 | unique_future<_Res> | |
c910ceff | 641 | get_future() |
c36abf03 | 642 | { return unique_future<_Res>(_M_future); } |
c910ceff | 643 | |
c36abf03 | 644 | // Setting the result |
c910ceff | 645 | void |
c36abf03 | 646 | set_value(const _Res& __r) |
c910ceff JW |
647 | { |
648 | if (!_M_satisfied()) | |
649 | _M_storage->_M_set(__r); | |
650 | _M_future->_M_set_result(std::move(_M_storage)); | |
651 | } | |
652 | ||
653 | void | |
c36abf03 | 654 | set_value(_Res&& __r) |
c910ceff JW |
655 | { |
656 | if (!_M_satisfied()) | |
657 | _M_storage->_M_set(_Mover::_S_move(__r)); | |
658 | _M_future->_M_set_result(std::move(_M_storage)); | |
659 | } | |
660 | ||
661 | void | |
662 | set_exception(exception_ptr __p) | |
663 | { | |
664 | if (!_M_satisfied()) | |
665 | _M_storage->_M_error = __p; | |
666 | _M_future->_M_set_result(std::move(_M_storage)); | |
667 | } | |
668 | ||
669 | private: | |
c910ceff | 670 | bool _M_satisfied() { return !static_cast<bool>(_M_storage); } |
c910ceff JW |
671 | }; |
672 | ||
c36abf03 BK |
673 | /// Partial specialization for promise<R&> |
674 | template<typename _Res> | |
675 | class promise<_Res&> | |
c910ceff | 676 | { |
c36abf03 BK |
677 | template<typename> friend class packaged_task; |
678 | typedef __future_base::_State _State; | |
679 | ||
680 | typedef __future_base::_Result<_Res&> result_type; | |
681 | ||
682 | shared_ptr<_State> _M_future; | |
683 | typename __future_base::_Ptr<result_type>::type _M_storage; | |
684 | ||
c910ceff JW |
685 | public: |
686 | promise() | |
c36abf03 | 687 | : _M_future(std::make_shared<_State>()), _M_storage(new result_type()) |
c910ceff JW |
688 | { } |
689 | ||
690 | promise(promise&& __rhs) | |
c36abf03 BK |
691 | : _M_future(std::move(__rhs._M_future)), |
692 | _M_storage(std::move(__rhs._M_storage)) | |
c910ceff JW |
693 | { } |
694 | ||
695 | // TODO: requires allocator concepts | |
696 | /* | |
697 | template<typename _Allocator> | |
698 | promise(allocator_arg_t, const _Allocator& __a); | |
699 | ||
700 | template<typename _Allocator> | |
701 | promise(allocator_arg_t, const _Allocator&, promise&& __rhs); | |
702 | */ | |
703 | ||
704 | promise(const promise&) = delete; | |
705 | ||
706 | ~promise() | |
707 | { | |
708 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
709 | _M_future->_M_break_promise(std::move(_M_storage)); | |
710 | } | |
711 | ||
c36abf03 | 712 | // Assignment |
c910ceff JW |
713 | promise& |
714 | operator=(promise&& __rhs) | |
715 | { | |
716 | promise(std::move(__rhs)).swap(*this); | |
717 | return *this; | |
718 | } | |
719 | ||
720 | promise& operator=(const promise&) = delete; | |
721 | ||
722 | void | |
723 | swap(promise& __rhs) | |
724 | { | |
725 | _M_future.swap(__rhs._M_future); | |
726 | _M_storage.swap(__rhs._M_storage); | |
727 | } | |
728 | ||
c36abf03 BK |
729 | // Retrieving the result |
730 | unique_future<_Res&> | |
c910ceff | 731 | get_future() |
c36abf03 | 732 | { return unique_future<_Res&>(_M_future); } |
c910ceff | 733 | |
c36abf03 | 734 | // Setting the result |
c910ceff | 735 | void |
c36abf03 | 736 | set_value(_Res& __r) |
c910ceff JW |
737 | { |
738 | if (!_M_satisfied()) | |
739 | _M_storage->_M_value_ptr = &__r; | |
740 | _M_future->_M_set_result(std::move(_M_storage)); | |
741 | } | |
742 | ||
743 | void | |
744 | set_exception(exception_ptr __p) | |
745 | { | |
746 | if (!_M_satisfied()) | |
747 | _M_storage->_M_error = __p; | |
748 | _M_future->_M_set_result(std::move(_M_storage)); | |
749 | } | |
750 | ||
751 | private: | |
c910ceff | 752 | bool _M_satisfied() { return !static_cast<bool>(_M_storage); } |
c910ceff JW |
753 | }; |
754 | ||
c36abf03 | 755 | /// Explicit specialization for promise<void> |
c910ceff JW |
756 | template<> |
757 | class promise<void> | |
758 | { | |
c36abf03 BK |
759 | template<typename> friend class packaged_task; |
760 | typedef __future_base::_State _State; | |
761 | typedef __future_base::_Result<void> result_type; | |
762 | ||
763 | shared_ptr<__future_base::_State> _M_future; | |
764 | typename __future_base::_Ptr<result_type>::type _M_storage; | |
765 | ||
c910ceff JW |
766 | public: |
767 | promise() | |
c36abf03 BK |
768 | : _M_future(std::make_shared<_State>()), |
769 | _M_storage(new result_type()) | |
c910ceff JW |
770 | { } |
771 | ||
772 | promise(promise&& __rhs) | |
773 | : _M_future(std::move(__rhs._M_future)), | |
774 | _M_storage(std::move(__rhs._M_storage)) | |
775 | { } | |
776 | ||
777 | // TODO: requires allocator concepts | |
778 | /* | |
779 | template<typename _Allocator> | |
780 | promise(allocator_arg_t, const _Allocator& __a); | |
781 | ||
782 | template<typename _Allocator> | |
783 | promise(allocator_arg_t, const _Allocator&, promise&& __rhs); | |
784 | */ | |
785 | ||
786 | promise(const promise&) = delete; | |
787 | ||
788 | ~promise() | |
789 | { | |
790 | if (static_cast<bool>(_M_future) && !_M_future.unique()) | |
791 | _M_future->_M_break_promise(std::move(_M_storage)); | |
792 | } | |
793 | ||
c36abf03 | 794 | // Assignment |
c910ceff JW |
795 | promise& |
796 | operator=(promise&& __rhs) | |
797 | { | |
798 | promise(std::move(__rhs)).swap(*this); | |
799 | return *this; | |
800 | } | |
801 | ||
802 | promise& operator=(const promise&) = delete; | |
803 | ||
804 | void | |
805 | swap(promise& __rhs) | |
806 | { | |
807 | _M_future.swap(__rhs._M_future); | |
808 | _M_storage.swap(__rhs._M_storage); | |
809 | } | |
810 | ||
c36abf03 | 811 | // Retrieving the result |
c910ceff JW |
812 | unique_future<void> |
813 | get_future() | |
814 | { return unique_future<void>(_M_future); } | |
815 | ||
c36abf03 | 816 | // Setting the result |
c910ceff JW |
817 | void |
818 | set_value() | |
819 | { | |
820 | _M_future->_M_set_result(std::move(_M_storage)); | |
821 | } | |
822 | ||
823 | void | |
824 | set_exception(exception_ptr __p) | |
825 | { | |
826 | if (!_M_satisfied()) | |
827 | _M_storage->_M_error = __p; | |
828 | _M_future->_M_set_result(std::move(_M_storage)); | |
829 | } | |
830 | ||
831 | private: | |
c910ceff | 832 | bool _M_satisfied() { return !static_cast<bool>(_M_storage); } |
c910ceff JW |
833 | }; |
834 | ||
835 | // TODO: requires allocator concepts | |
836 | /* | |
c36abf03 BK |
837 | template<typename _Res, class Alloc> |
838 | concept_map UsesAllocator<promise<_Res>, Alloc> | |
c910ceff JW |
839 | { |
840 | typedef Alloc allocator_type; | |
841 | } | |
842 | */ | |
c36abf03 BK |
843 | /// Primary template. |
844 | template<typename _Res, typename... _ArgTypes> | |
c910ceff JW |
845 | struct _Run_task |
846 | { | |
847 | static void | |
c36abf03 BK |
848 | _S_run(promise<_Res>& __p, function<_Res(_ArgTypes...)>& __f, |
849 | _ArgTypes... __args) | |
c910ceff JW |
850 | { |
851 | __p.set_value(__f(std::forward<_ArgTypes>(__args)...)); | |
852 | } | |
853 | }; | |
854 | ||
c36abf03 | 855 | /// Specialization used by packaged_task<void(...)> |
c910ceff JW |
856 | template<typename... _ArgTypes> |
857 | struct _Run_task<void, _ArgTypes...> | |
858 | { | |
859 | static void | |
860 | _S_run(promise<void>& __p, function<void(_ArgTypes...)>& __f, | |
c36abf03 | 861 | _ArgTypes... __args) |
c910ceff JW |
862 | { |
863 | __f(std::forward<_ArgTypes>(__args)...); | |
864 | __p.set_value(); | |
865 | } | |
866 | }; | |
867 | ||
c36abf03 | 868 | |
3259554a | 869 | /// packaged_task |
c36abf03 BK |
870 | template<typename _Res, typename... _ArgTypes> |
871 | class packaged_task<_Res(_ArgTypes...)> | |
c910ceff | 872 | { |
c36abf03 BK |
873 | function<_Res(_ArgTypes...)> _M_task; |
874 | promise<_Res> _M_promise; | |
875 | ||
c910ceff | 876 | public: |
c36abf03 | 877 | typedef _Res result_type; |
c910ceff | 878 | |
c36abf03 | 879 | // Construction and destruction |
c910ceff JW |
880 | packaged_task() { } |
881 | ||
882 | template<typename _Fn> | |
883 | explicit | |
884 | packaged_task(const _Fn& __fn) : _M_task(__fn) { } | |
885 | ||
886 | template<typename _Fn> | |
887 | explicit | |
888 | packaged_task(_Fn&& __fn) : _M_task(std::move(__fn)) { } | |
889 | ||
890 | explicit | |
c36abf03 | 891 | packaged_task(_Res(*__fn)(_ArgTypes...)) : _M_task(__fn) { } |
c910ceff JW |
892 | |
893 | // TODO: requires allocator concepts | |
894 | /* | |
895 | template<typename _Fn, typename _Allocator> | |
896 | explicit | |
897 | packaged_task(allocator_arg_t __tag, const _Allocator& __a, _Fn __fn) | |
898 | : _M_task(__tag, __a, __fn), _M_promise(__tag, __a) | |
899 | { } | |
900 | ||
901 | template<typename _Fn, typename _Allocator> | |
902 | explicit | |
903 | packaged_task(allocator_arg_t __tag, const _Allocator& __a, _Fn&& __fn) | |
904 | : _M_task(__tag, __a, std::move(__fn)), _M_promise(__tag, __a) | |
905 | { } | |
906 | */ | |
907 | ||
908 | ~packaged_task() = default; | |
909 | ||
c36abf03 | 910 | // No copy |
c910ceff JW |
911 | packaged_task(packaged_task&) = delete; |
912 | packaged_task& operator=(packaged_task&) = delete; | |
913 | ||
c36abf03 | 914 | // Move support |
c910ceff JW |
915 | packaged_task(packaged_task&& __other) |
916 | { this->swap(__other); } | |
917 | ||
918 | packaged_task& operator=(packaged_task&& __other) | |
919 | { | |
920 | packaged_task(std::move(__other)).swap(*this); | |
921 | return *this; | |
922 | } | |
923 | ||
924 | void | |
925 | swap(packaged_task& __other) | |
926 | { | |
927 | _M_task.swap(__other._M_task); | |
928 | _M_promise.swap(__other._M_promise); | |
929 | } | |
930 | ||
931 | explicit operator bool() const { return static_cast<bool>(_M_task); } | |
932 | ||
c36abf03 BK |
933 | // Result retrieval |
934 | unique_future<_Res> | |
c910ceff JW |
935 | get_future() |
936 | { | |
8d1b99e2 | 937 | __try |
c910ceff JW |
938 | { |
939 | return _M_promise.get_future(); | |
940 | } | |
8d1b99e2 | 941 | __catch (const future_error& __e) |
c910ceff | 942 | { |
8d1b99e2 | 943 | #ifdef __EXCEPTIONS |
c910ceff | 944 | if (__e.code() == future_errc::future_already_retrieved) |
8d1b99e2 BK |
945 | throw std::bad_function_call(); |
946 | throw; | |
947 | #endif | |
c910ceff JW |
948 | } |
949 | } | |
950 | ||
c36abf03 | 951 | // Execution |
c910ceff JW |
952 | void |
953 | operator()(_ArgTypes... __args) | |
954 | { | |
955 | if (!static_cast<bool>(_M_task) || _M_promise._M_satisfied()) | |
8d1b99e2 BK |
956 | { |
957 | #ifdef __EXCEPTIONS | |
958 | throw std::bad_function_call(); | |
959 | #else | |
960 | __builtin_abort(); | |
961 | #endif | |
962 | } | |
963 | ||
964 | __try | |
c910ceff | 965 | { |
c36abf03 | 966 | _Run_task<_Res, _ArgTypes...>::_S_run(_M_promise, _M_task, |
c910ceff JW |
967 | std::forward<_ArgTypes>(__args)...); |
968 | } | |
8d1b99e2 | 969 | __catch (...) |
c910ceff JW |
970 | { |
971 | _M_promise.set_exception(current_exception()); | |
972 | } | |
973 | } | |
974 | ||
c36abf03 | 975 | void reset() { promise<_Res>().swap(_M_promise); } |
c910ceff JW |
976 | }; |
977 | ||
c910ceff JW |
978 | #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 |
979 | // && _GLIBCXX_ATOMIC_BUILTINS_4 | |
980 | ||
41ca4246 BK |
981 | // @} group futures |
982 | } | |
983 | ||
c910ceff JW |
984 | #endif // __GXX_EXPERIMENTAL_CXX0X__ |
985 | ||
986 | #endif // _GLIBCXX_FUTURE |