]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/std/future
re PR c++/42358 ([C++0x] Assembler failure on libstdc++-v3/testsuite/23_containers...
[thirdparty/gcc.git] / libstdc++-v3 / include / std / future
CommitLineData
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
46namespace 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