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