blob: abfb77d020fbdf50d69a9674fb2b27f2f6ca2b2a [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===--------------------------- future -----------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_FUTURE
12#define _LIBCPP_FUTURE
13
14/*
15 future synopsis
16
17namespace std
18{
19
20enum class future_errc
21{
22 broken_promise,
23 future_already_retrieved,
24 promise_already_satisfied,
25 no_state
26};
27
28enum class launch
29{
30 any,
31 async,
32 sync
33};
34
35enum class future_status
36{
37 ready,
38 timeout,
39 deferred
40};
41
42template <> struct is_error_code_enum<future_errc> : public true_type { };
43error_code make_error_code(future_errc e);
44error_condition make_error_condition(future_errc e);
45
46const error_category& future_category();
47
48class future_error
49 : public logic_error
50{
51public:
52 future_error(error_code ec); // exposition only
53
54 const error_code& code() const throw();
55 const char* what() const throw();
56};
57
58template <class R>
59class promise
60{
61public:
62 promise();
63 template <class Allocator>
64 promise(allocator_arg_t, const Allocator& a);
65 promise(promise&& rhs);
66 promise(const promise& rhs) = delete;
67 ~promise();
68
69 // assignment
70 promise& operator=(promise&& rhs);
71 promise& operator=(const promise& rhs) = delete;
72 void swap(promise& other);
73
74 // retrieving the result
75 future<R> get_future();
76
77 // setting the result
78 void set_value(const R& r);
79 void set_value(R&& r);
80 void set_exception(exception_ptr p);
81
82 // setting the result with deferred notification
83 void set_value_at_thread_exit(const R& r);
84 void set_value_at_thread_exit(R&& r);
85 void set_exception_at_thread_exit(exception_ptr p);
86};
87
88template <class R>
89class promise<R&>
90{
91public:
92 promise();
93 template <class Allocator>
94 promise(allocator_arg_t, const Allocator& a);
95 promise(promise&& rhs);
96 promise(const promise& rhs) = delete;
97 ~promise();
98
99 // assignment
100 promise& operator=(promise&& rhs);
101 promise& operator=(const promise& rhs) = delete;
102 void swap(promise& other);
103
104 // retrieving the result
Howard Hinnant47499b12010-08-27 20:10:19 +0000105 future<R&> get_future();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000106
107 // setting the result
108 void set_value(R& r);
109 void set_exception(exception_ptr p);
110
111 // setting the result with deferred notification
112 void set_value_at_thread_exit(R&);
113 void set_exception_at_thread_exit(exception_ptr p);
114};
115
116template <>
117class promise<void>
118{
119public:
120 promise();
121 template <class Allocator>
122 promise(allocator_arg_t, const Allocator& a);
123 promise(promise&& rhs);
124 promise(const promise& rhs) = delete;
125 ~promise();
126
127 // assignment
128 promise& operator=(promise&& rhs);
129 promise& operator=(const promise& rhs) = delete;
130 void swap(promise& other);
131
132 // retrieving the result
Howard Hinnant47499b12010-08-27 20:10:19 +0000133 future<void> get_future();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000134
135 // setting the result
136 void set_value();
137 void set_exception(exception_ptr p);
138
139 // setting the result with deferred notification
140 void set_value_at_thread_exit();
141 void set_exception_at_thread_exit(exception_ptr p);
142};
143
144template <class R> void swap(promise<R>& x, promise<R>& y);
145
146template <class R, class Alloc>
147 struct uses_allocator<promise<R>, Alloc> : public true_type {};
148
149template <class R>
150class future
151{
152public:
153 future();
154 future(future&&);
155 future(const future& rhs) = delete;
156 ~future();
157 future& operator=(const future& rhs) = delete;
158 future& operator=(future&&);
159
160 // retrieving the value
161 R get();
162
163 // functions to check state
164 bool valid() const;
165
166 void wait() const;
167 template <class Rep, class Period>
168 future_status
169 wait_for(const chrono::duration<Rep, Period>& rel_time) const;
170 template <class Clock, class Duration>
171 future_status
172 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
173};
174
175template <class R>
176class future<R&>
177{
178public:
179 future();
180 future(future&&);
181 future(const future& rhs) = delete;
182 ~future();
183 future& operator=(const future& rhs) = delete;
184 future& operator=(future&&);
185
186 // retrieving the value
187 R& get();
188
189 // functions to check state
190 bool valid() const;
191
192 void wait() const;
193 template <class Rep, class Period>
194 future_status
195 wait_for(const chrono::duration<Rep, Period>& rel_time) const;
196 template <class Clock, class Duration>
197 future_status
198 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
199};
200
201template <>
202class future<void>
203{
204public:
205 future();
206 future(future&&);
207 future(const future& rhs) = delete;
208 ~future();
209 future& operator=(const future& rhs) = delete;
210 future& operator=(future&&);
211
212 // retrieving the value
213 void get();
214
215 // functions to check state
216 bool valid() const;
217
218 void wait() const;
219 template <class Rep, class Period>
220 future_status
221 wait_for(const chrono::duration<Rep, Period>& rel_time) const;
222 template <class Clock, class Duration>
223 future_status
224 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
225};
226
227template <class R>
228class shared_future
229{
230public:
231 shared_future();
232 shared_future(const shared_future& rhs);
233 shared_future(future<R>&&);
234 shared_future(shared_future&& rhs);
235 ~shared_future();
236 shared_future& operator=(const shared_future& rhs);
237 shared_future& operator=(shared_future&& rhs);
238
239 // retrieving the value
240 const R& get() const;
241
242 // functions to check state
243 bool valid() const;
244
245 void wait() const;
246 template <class Rep, class Period>
247 future_status
248 wait_for(const chrono::duration<Rep, Period>& rel_time) const;
249 template <class Clock, class Duration>
250 future_status
251 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
252};
253
254template <class R>
255class shared_future<R&>
256{
257public:
258 shared_future();
259 shared_future(const shared_future& rhs);
260 shared_future(future<R>&&);
261 shared_future(shared_future&& rhs);
262 ~shared_future();
263 shared_future& operator=(const shared_future& rhs);
264 shared_future& operator=(shared_future&& rhs);
265
266 // retrieving the value
267 R& get() const;
268
269 // functions to check state
270 bool valid() const;
271
272 void wait() const;
273 template <class Rep, class Period>
274 future_status
275 wait_for(const chrono::duration<Rep, Period>& rel_time) const;
276 template <class Clock, class Duration>
277 future_status
278 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
279};
280
281template <>
282class shared_future<void>
283{
284public:
285 shared_future();
286 shared_future(const shared_future& rhs);
287 shared_future(future<R>&&);
288 shared_future(shared_future&& rhs);
289 ~shared_future();
290 shared_future& operator=(const shared_future& rhs);
291 shared_future& operator=(shared_future&& rhs);
292
293 // retrieving the value
294 void get() const;
295
296 // functions to check state
297 bool valid() const;
298
299 void wait() const;
300 template <class Rep, class Period>
301 future_status
302 wait_for(const chrono::duration<Rep, Period>& rel_time) const;
303 template <class Clock, class Duration>
304 future_status
305 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
306};
307
308template <class R>
309class atomic_future
310{
311public:
312 atomic_future();
313 atomic_future(const atomic_future& rhs);
314 atomic_future(future<R>&&);
315 ~atomic_future();
316 atomic_future& operator=(const atomic_future& rhs);
317
318 // retrieving the value
319 const R& get() const;
320
321 // functions to check state
322 bool valid() const;
323
324 void wait() const;
325 template <class Rep, class Period>
326 future_status
327 wait_for(const chrono::duration<Rep, Period>& rel_time) const;
328 template <class Clock, class Duration>
329 future_status
330 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
331};
332
333template <class R>
334class atomic_future<R&>
335{
336public:
337 atomic_future();
338 atomic_future(const atomic_future& rhs);
339 atomic_future(future<R>&&);
340 ~atomic_future();
341 atomic_future& operator=(const atomic_future& rhs);
342
343 // retrieving the value
344 R& get() const;
345
346 // functions to check state
347 bool valid() const;
348
349 void wait() const;
350 template <class Rep, class Period>
351 future_status
352 wait_for(const chrono::duration<Rep, Period>& rel_time) const;
353 template <class Clock, class Duration>
354 future_status
355 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
356};
357
358template <>
359class atomic_future<void>
360{
361public:
362 atomic_future();
363 atomic_future(const atomic_future& rhs);
364 atomic_future(future<R>&&);
365 ~atomic_future();
366 atomic_future& operator=(const atomic_future& rhs);
367
368 // retrieving the value
369 void get() const;
370
371 // functions to check state
372 bool valid() const;
373
374 void wait() const;
375 template <class Rep, class Period>
376 future_status
377 wait_for(const chrono::duration<Rep, Period>& rel_time) const;
378 template <class Clock, class Duration>
379 future_status
380 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
381};
382
383template <class F, class... Args>
384 future<typename result_of<F(Args...)>::type>
385 async(F&& f, Args&&... args);
386
387template <class F, class... Args>
388 future<typename result_of<F(Args...)>::type>
389 async(launch policy, F&& f, Args&&... args);
390
Howard Hinnantf5256e12010-05-11 21:36:01 +0000391template <class> class packaged_task; // undefined
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000392
393template <class R, class... ArgTypes>
394class packaged_task<R(ArgTypes...)>
395{
396public:
397 typedef R result_type;
398
399 // construction and destruction
400 packaged_task();
401 template <class F>
402 explicit packaged_task(F f);
403 template <class F, class Allocator>
404 explicit packaged_task(allocator_arg_t, const Allocator& a, F f);
405 explicit packaged_task(R(*f)(ArgTypes...));
406 template <class F>
407 explicit packaged_task(F&& f);
408 template <class F, class Allocator>
409 explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);
410 ~packaged_task();
411
412 // no copy
413 packaged_task(packaged_task&) = delete;
414 packaged_task& operator=(packaged_task&) = delete;
415
416 // move support
417 packaged_task(packaged_task&& other);
418 packaged_task& operator=(packaged_task&& other);
419 void swap(packaged_task& other);
420
421 explicit operator bool() const;
422
423 // result retrieval
424 future<R> get_future();
425
426 // execution
427 void operator()(ArgTypes... );
428 void make_ready_at_thread_exit(ArgTypes...);
429
430 void reset();
431};
432
433template <class R>
434 void swap(packaged_task<R(ArgTypes...)&, packaged_task<R(ArgTypes...)>&);
435
436template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>;
437
438} // std
439
440*/
441
442#include <__config>
443#include <system_error>
Howard Hinnant47499b12010-08-27 20:10:19 +0000444#include <memory>
445#include <chrono>
446#include <exception>
447#include <__mutex_base>
448#include <thread>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000449
450#pragma GCC system_header
451
452_LIBCPP_BEGIN_NAMESPACE_STD
453
454//enum class future_errc
455struct future_errc
456{
457enum _ {
458 broken_promise,
459 future_already_retrieved,
460 promise_already_satisfied,
461 no_state
462};
463
464 _ __v_;
465
466 future_errc(_ __v) : __v_(__v) {}
467 operator int() const {return __v_;}
468
469};
470
Howard Hinnanta6521722010-08-25 17:32:05 +0000471template <> struct is_error_code_enum<future_errc> : public true_type {};
472
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000473//enum class launch
474struct launch
475{
476enum _ {
477 any,
478 async,
479 sync
480};
481
482 _ __v_;
483
484 launch(_ __v) : __v_(__v) {}
485 operator int() const {return __v_;}
486
487};
488
489//enum class future_status
490struct future_status
491{
492enum _ {
493 ready,
494 timeout,
495 deferred
496};
497
498 _ __v_;
499
500 future_status(_ __v) : __v_(__v) {}
501 operator int() const {return __v_;}
502
503};
504
Howard Hinnanta6521722010-08-25 17:32:05 +0000505const error_category& future_category();
506
507inline _LIBCPP_INLINE_VISIBILITY
508error_code
509make_error_code(future_errc __e)
510{
511 return error_code(static_cast<int>(__e), future_category());
512}
513
514inline _LIBCPP_INLINE_VISIBILITY
515error_condition
516make_error_condition(future_errc __e)
517{
518 return error_condition(static_cast<int>(__e), future_category());
519}
520
521class future_error
522 : public logic_error
523{
524 error_code __ec_;
525public:
526 future_error(error_code __ec);
527
528 const error_code& code() const throw() {return __ec_;}
529};
530
Howard Hinnant47499b12010-08-27 20:10:19 +0000531class __assoc_sub_state
532 : public __shared_count
533{
534protected:
535 exception_ptr __exception_;
536 mutable mutex __mut_;
537 mutable condition_variable __cv_;
538 unsigned __state_;
539
540 virtual void __on_zero_shared();
541
542public:
543 enum
544 {
545 __constructed = 1,
546 __future_attached = 2,
547 ready = 4,
548 deferred = 8
549 };
550
551 __assoc_sub_state() : __state_(0) {}
552
553 bool __has_value() const
554 {return (__state_ & __constructed) || (__exception_ != nullptr);}
555
556 void __set_future_attached() {__state_ |= __future_attached;}
557 bool __has_future_attached() const {return __state_ & __future_attached;}
558
559 void __make_ready();
560 bool __is_ready() const {return __state_ & ready;}
561
562 void set_value();
563 void set_value_at_thread_exit();
564
565 void set_exception(exception_ptr __p);
566 void set_exception_at_thread_exit(exception_ptr __p);
567
568 void copy();
569
570 void wait() const;
571 template <class _Rep, class _Period>
572 future_status
573 wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const;
574 template <class _Clock, class _Duration>
575 future_status
576 wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const;
577};
578
Howard Hinnantf39daa82010-08-28 21:01:06 +0000579template <class _Clock, class _Duration>
580future_status
581__assoc_sub_state::wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
582{
583 unique_lock<mutex> __lk(__mut_);
584 while (!(__state_ & (ready | deferred)) && _Clock::now() < __abs_time)
585 __cv_.wait_until(__lk, __abs_time);
586 if (__state_ & ready)
587 return future_status::ready;
588 if (__state_ & deferred)
589 return future_status::deferred;
590 return future_status::timeout;
591}
592
593template <class _Rep, class _Period>
594inline _LIBCPP_INLINE_VISIBILITY
595future_status
596__assoc_sub_state::wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
597{
598 return wait_until(chrono::monotonic_clock::now() + __rel_time);
599}
600
Howard Hinnant47499b12010-08-27 20:10:19 +0000601template <class _R>
602class __assoc_state
603 : public __assoc_sub_state
604{
605 typedef __assoc_sub_state base;
606 typedef typename aligned_storage<sizeof(_R), alignment_of<_R>::value>::type _U;
607protected:
608 _U __value_;
609
610 virtual void __on_zero_shared();
611public:
612
613 template <class _Arg>
614#ifdef _LIBCPP_MOVE
615 void set_value(_Arg&& __arg);
616#else
617 void set_value(_Arg& __arg);
618#endif
619
620 template <class _Arg>
621#ifdef _LIBCPP_MOVE
622 void set_value_at_thread_exit(_Arg&& __arg);
623#else
624 void set_value_at_thread_exit(_Arg& __arg);
625#endif
626
627 _R move();
628 typename add_lvalue_reference<_R>::type copy();
629};
630
631template <class _R>
632void
633__assoc_state<_R>::__on_zero_shared()
634{
635 if (this->__state_ & base::__constructed)
636 reinterpret_cast<_R*>(&__value_)->~_R();
637 delete this;
638}
639
640template <class _R>
641template <class _Arg>
642void
643#ifdef _LIBCPP_MOVE
644__assoc_state<_R>::set_value(_Arg&& __arg)
645#else
646__assoc_state<_R>::set_value(_Arg& __arg)
647#endif
648{
649 unique_lock<mutex> __lk(this->__mut_);
650 if (this->__has_value())
651 throw future_error(make_error_code(future_errc::promise_already_satisfied));
652 ::new(&__value_) _R(_STD::forward<_Arg>(__arg));
653 this->__state_ |= base::__constructed | base::ready;
654 __lk.unlock();
655 __cv_.notify_all();
656}
657
658template <class _R>
659template <class _Arg>
660void
661#ifdef _LIBCPP_MOVE
662__assoc_state<_R>::set_value_at_thread_exit(_Arg&& __arg)
663#else
664__assoc_state<_R>::set_value_at_thread_exit(_Arg& __arg)
665#endif
666{
667 unique_lock<mutex> __lk(this->__mut_);
668 if (this->__has_value())
669 throw future_error(make_error_code(future_errc::promise_already_satisfied));
670 ::new(&__value_) _R(_STD::forward<_Arg>(__arg));
671 this->__state_ |= base::__constructed;
672 __thread_local_data->__make_ready_at_thread_exit(this);
673 __lk.unlock();
674}
675
676template <class _R>
677_R
678__assoc_state<_R>::move()
679{
680 unique_lock<mutex> __lk(this->__mut_);
681 while (!this->__is_ready())
682 this->__cv_.wait(__lk);
683 if (this->__exception_ != nullptr)
684 rethrow_exception(this->__exception_);
685 return _STD::move(*reinterpret_cast<_R*>(&__value_));
686}
687
688template <class _R>
689typename add_lvalue_reference<_R>::type
690__assoc_state<_R>::copy()
691{
692 unique_lock<mutex> __lk(this->__mut_);
693 while (!this->__is_ready())
694 this->__cv_.wait(__lk);
695 if (this->__exception_ != nullptr)
696 rethrow_exception(this->__exception_);
697 return *reinterpret_cast<_R*>(&__value_);
698}
699
Howard Hinnantf39daa82010-08-28 21:01:06 +0000700template <class _R>
701class __assoc_state<_R&>
702 : public __assoc_sub_state
703{
704 typedef __assoc_sub_state base;
705 typedef _R* _U;
706protected:
707 _U __value_;
708
709 virtual void __on_zero_shared();
710public:
711
712 void set_value(_R& __arg);
713 void set_value_at_thread_exit(_R& __arg);
714
715 _R& copy();
716};
717
718template <class _R>
719void
720__assoc_state<_R&>::__on_zero_shared()
721{
722 delete this;
723}
724
725template <class _R>
726void
727__assoc_state<_R&>::set_value(_R& __arg)
728{
729 unique_lock<mutex> __lk(this->__mut_);
730 if (this->__has_value())
731 throw future_error(make_error_code(future_errc::promise_already_satisfied));
732 __value_ = &__arg;
733 this->__state_ |= base::__constructed | base::ready;
734 __lk.unlock();
735 __cv_.notify_all();
736}
737
738template <class _R>
739void
740__assoc_state<_R&>::set_value_at_thread_exit(_R& __arg)
741{
742 unique_lock<mutex> __lk(this->__mut_);
743 if (this->__has_value())
744 throw future_error(make_error_code(future_errc::promise_already_satisfied));
745 __value_ = &__arg;
746 this->__state_ |= base::__constructed;
747 __thread_local_data->__make_ready_at_thread_exit(this);
748 __lk.unlock();
749}
750
751template <class _R>
752_R&
753__assoc_state<_R&>::copy()
754{
755 unique_lock<mutex> __lk(this->__mut_);
756 while (!this->__is_ready())
757 this->__cv_.wait(__lk);
758 if (this->__exception_ != nullptr)
759 rethrow_exception(this->__exception_);
760 return *__value_;
761}
762
Howard Hinnant47499b12010-08-27 20:10:19 +0000763template <class _R, class _Alloc>
764class __assoc_state_alloc
765 : public __assoc_state<_R>
766{
767 typedef __assoc_state<_R> base;
768 _Alloc __alloc_;
769
770 virtual void __on_zero_shared();
771public:
772 explicit __assoc_state_alloc(const _Alloc& __a)
773 : __alloc_(__a) {}
774};
775
776template <class _R, class _Alloc>
777void
778__assoc_state_alloc<_R, _Alloc>::__on_zero_shared()
779{
780 if (this->__state_ & base::__constructed)
781 reinterpret_cast<_R*>(&this->__value_)->~_R();
782 typename _Alloc::template rebind<__assoc_state_alloc>::other __a(__alloc_);
783 this->~__assoc_state_alloc();
784 __a.deallocate(this, 1);
785}
786
Howard Hinnantf39daa82010-08-28 21:01:06 +0000787template <class _R, class _Alloc>
788class __assoc_state_alloc<_R&, _Alloc>
789 : public __assoc_state<_R&>
790{
791 typedef __assoc_state<_R&> base;
792 _Alloc __alloc_;
793
794 virtual void __on_zero_shared();
795public:
796 explicit __assoc_state_alloc(const _Alloc& __a)
797 : __alloc_(__a) {}
798};
799
800template <class _R, class _Alloc>
801void
802__assoc_state_alloc<_R&, _Alloc>::__on_zero_shared()
803{
804 typename _Alloc::template rebind<__assoc_state_alloc>::other __a(__alloc_);
805 this->~__assoc_state_alloc();
806 __a.deallocate(this, 1);
807}
808
Howard Hinnant47499b12010-08-27 20:10:19 +0000809template <class _Alloc>
810class __assoc_sub_state_alloc
811 : public __assoc_sub_state
812{
813 typedef __assoc_sub_state base;
814 _Alloc __alloc_;
815
816 virtual void __on_zero_shared();
817public:
818 explicit __assoc_sub_state_alloc(const _Alloc& __a)
819 : __alloc_(__a) {}
820};
821
822template <class _Alloc>
823void
824__assoc_sub_state_alloc<_Alloc>::__on_zero_shared()
825{
826 this->~base();
Howard Hinnantf39daa82010-08-28 21:01:06 +0000827 typename _Alloc::template rebind<__assoc_sub_state_alloc>::other __a(__alloc_);
Howard Hinnant47499b12010-08-27 20:10:19 +0000828 this->~__assoc_sub_state_alloc();
829 __a.deallocate(this, 1);
830}
831
832template <class> class promise;
833
834// future
835
836template <class _R>
837class future
838{
839 __assoc_state<_R>* __state_;
840
841 explicit future(__assoc_state<_R>* __state);
842
843 template <class> friend class promise;
844public:
845 future() : __state_(nullptr) {}
846#ifdef _LIBCPP_MOVE
847 future(future&& __rhs)
848 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
849 future(const future&) = delete;
850 future& operator=(const future&) = delete;
851 future& operator=(future&& __rhs)
852 {
853 future(std::move(__rhs)).swap(*this);
854 return *this;
855 }
856#else // _LIBCPP_MOVE
857private:
858 future(const future&);
859 future& operator=(const future&);
860public:
861#endif // _LIBCPP_MOVE
862 ~future();
863
864 // retrieving the value
865 _R get();
866
867 void swap(future& __rhs) {_STD::swap(__state_, __rhs.__state_);}
868
869 // functions to check state
870 bool valid() const {return __state_ != nullptr;}
871
872 void wait() const {__state_->wait();}
873 template <class _Rep, class _Period>
874 future_status
875 wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
876 {return __state_->wait_for(__rel_time);}
877 template <class _Clock, class _Duration>
878 future_status
879 wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
880 {return __state_->wait_until(__abs_time);}
881};
882
883template <class _R>
884future<_R>::future(__assoc_state<_R>* __state)
885 : __state_(__state)
886{
887 if (__state_->__has_future_attached())
888 throw future_error(make_error_code(future_errc::future_already_retrieved));
889 __state_->__add_shared();
890}
891
892template <class _R>
893future<_R>::~future()
894{
895 if (__state_)
896 __state_->__release_shared();
897}
898
899template <class _R>
900_R
901future<_R>::get()
902{
903 __assoc_state<_R>* __s = __state_;
904 __state_ = nullptr;
905 return __s->move();
906}
907
908template <class _R>
909class future<_R&>
910{
911 __assoc_state<_R&>* __state_;
912
913 explicit future(__assoc_state<_R&>* __state);
914
915 template <class> friend class promise;
916public:
917 future() : __state_(nullptr) {}
918#ifdef _LIBCPP_MOVE
919 future(future&& __rhs)
920 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
921 future(const future&) = delete;
922 future& operator=(const future&) = delete;
923 future& operator=(future&& __rhs)
924 {
925 future(std::move(__rhs)).swap(*this);
926 return *this;
927 }
928#else // _LIBCPP_MOVE
929private:
930 future(const future&);
931 future& operator=(const future&);
932public:
933#endif // _LIBCPP_MOVE
934 ~future();
935
936 // retrieving the value
937 _R& get();
938
939 void swap(future& __rhs) {_STD::swap(__state_, __rhs.__state_);}
940
941 // functions to check state
942 bool valid() const {return __state_ != nullptr;}
943
944 void wait() const {__state_->wait();}
945 template <class _Rep, class _Period>
946 future_status
947 wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
948 {return __state_->wait_for(__rel_time);}
949 template <class _Clock, class _Duration>
950 future_status
951 wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
952 {return __state_->wait_until(__abs_time);}
953};
954
955template <class _R>
956future<_R&>::future(__assoc_state<_R&>* __state)
957 : __state_(__state)
958{
959 if (__state_->__has_future_attached())
960 throw future_error(make_error_code(future_errc::future_already_retrieved));
961 __state_->__add_shared();
962}
963
964template <class _R>
965future<_R&>::~future()
966{
967 if (__state_)
968 __state_->__release_shared();
969}
970
971template <class _R>
972_R&
973future<_R&>::get()
974{
Howard Hinnantf39daa82010-08-28 21:01:06 +0000975 __assoc_state<_R&>* __s = __state_;
Howard Hinnant47499b12010-08-27 20:10:19 +0000976 __state_ = nullptr;
977 return __s->copy();
978}
979
980template <>
981class future<void>
982{
983 __assoc_sub_state* __state_;
984
985 explicit future(__assoc_sub_state* __state);
986
987 template <class> friend class promise;
988public:
989 future() : __state_(nullptr) {}
990#ifdef _LIBCPP_MOVE
991 future(future&& __rhs)
992 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
993 future(const future&) = delete;
994 future& operator=(const future&) = delete;
995 future& operator=(future&& __rhs)
996 {
997 future(std::move(__rhs)).swap(*this);
998 return *this;
999 }
1000#else // _LIBCPP_MOVE
1001private:
1002 future(const future&);
1003 future& operator=(const future&);
1004public:
1005#endif // _LIBCPP_MOVE
1006 ~future();
1007
1008 // retrieving the value
1009 void get();
1010
1011 void swap(future& __rhs) {_STD::swap(__state_, __rhs.__state_);}
1012
1013 // functions to check state
1014 bool valid() const {return __state_ != nullptr;}
1015
1016 void wait() const {__state_->wait();}
1017 template <class _Rep, class _Period>
1018 future_status
1019 wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
1020 {return __state_->wait_for(__rel_time);}
1021 template <class _Clock, class _Duration>
1022 future_status
1023 wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
1024 {return __state_->wait_until(__abs_time);}
1025};
1026
1027// promise<R>
1028
1029template <class _R>
1030class promise
1031{
1032 __assoc_state<_R>* __state_;
1033public:
1034 promise();
1035 template <class _Alloc>
1036 promise(allocator_arg_t, const _Alloc& __a);
1037#ifdef _LIBCPP_MOVE
1038 promise(promise&& __rhs)
1039 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
1040 promise(const promise& __rhs) = delete;
1041#else // _LIBCPP_MOVE
1042private:
1043 promise(const promise& __rhs);
1044public:
1045#endif // _LIBCPP_MOVE
1046 ~promise();
1047
1048 // assignment
1049#ifdef _LIBCPP_MOVE
1050 promise& operator=(promise&& __rhs)
1051 {
1052 promise(std::move(__rhs)).swap(*this);
1053 return *this;
1054 }
1055 promise& operator=(const promise& __rhs) = delete;
1056#else // _LIBCPP_MOVE
1057private:
1058 promise& operator=(const promise& __rhs);
1059public:
1060#endif // _LIBCPP_MOVE
1061 void swap(promise& __rhs) {_STD::swap(__state_, __rhs.__state_);}
1062
1063 // retrieving the result
1064 future<_R> get_future();
1065
1066 // setting the result
1067 void set_value(const _R& __r);
1068#ifdef _LIBCPP_MOVE
1069 void set_value(_R&& __r);
1070#endif
1071 void set_exception(exception_ptr __p);
1072
1073 // setting the result with deferred notification
1074 void set_value_at_thread_exit(const _R& __r);
1075#ifdef _LIBCPP_MOVE
1076 void set_value_at_thread_exit(_R&& __r);
1077#endif
1078 void set_exception_at_thread_exit(exception_ptr __p);
1079};
1080
1081template <class _R>
1082promise<_R>::promise()
1083 : __state_(new __assoc_state<_R>)
1084{
1085}
1086
1087template <class _R>
1088template <class _Alloc>
1089promise<_R>::promise(allocator_arg_t, const _Alloc& __a0)
1090{
1091 typedef typename _Alloc::template rebind<__assoc_state_alloc<_R, _Alloc> >::other _A2;
1092 typedef __allocator_destructor<_A2> _D2;
1093 _A2 __a(__a0);
1094 unique_ptr<__assoc_state_alloc<_R, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
1095 ::new(__hold.get()) __assoc_state_alloc<_R, _Alloc>(__a0);
1096 __state_ = __hold.release();
1097}
1098
1099template <class _R>
1100promise<_R>::~promise()
1101{
1102 if (__state_)
1103 {
1104 if (!__state_->__has_value() && __state_->use_count() > 1)
1105 __state_->set_exception(make_exception_ptr(
1106 future_error(make_error_code(future_errc::broken_promise))
1107 ));
1108 __state_->__release_shared();
1109 }
1110}
1111
1112template <class _R>
1113future<_R>
1114promise<_R>::get_future()
1115{
1116 if (__state_ == nullptr)
1117 throw future_error(make_error_code(future_errc::no_state));
1118 return future<_R>(__state_);
1119}
1120
1121template <class _R>
1122void
1123promise<_R>::set_value(const _R& __r)
1124{
1125 if (__state_ == nullptr)
1126 throw future_error(make_error_code(future_errc::no_state));
1127 __state_->set_value(__r);
1128}
1129
1130#ifdef _LIBCPP_MOVE
1131
1132template <class _R>
1133void
1134promise<_R>::set_value(_R&& __r)
1135{
1136 if (__state_ == nullptr)
1137 throw future_error(make_error_code(future_errc::no_state));
1138 __state_->set_value(_STD::move(__r));
1139}
1140
1141#endif // _LIBCPP_MOVE
1142
1143template <class _R>
1144void
1145promise<_R>::set_exception(exception_ptr __p)
1146{
1147 if (__state_ == nullptr)
1148 throw future_error(make_error_code(future_errc::no_state));
1149 __state_->set_exception(__p);
1150}
1151
1152template <class _R>
1153void
1154promise<_R>::set_value_at_thread_exit(const _R& __r)
1155{
1156 if (__state_ == nullptr)
1157 throw future_error(make_error_code(future_errc::no_state));
1158 __state_->set_value_at_thread_exit(__r);
1159}
1160
1161#ifdef _LIBCPP_MOVE
1162
1163template <class _R>
1164void
1165promise<_R>::set_value_at_thread_exit(_R&& __r)
1166{
1167 if (__state_ == nullptr)
1168 throw future_error(make_error_code(future_errc::no_state));
1169 __state_->set_value_at_thread_exit(_STD::move(__r));
1170}
1171
1172#endif // _LIBCPP_MOVE
1173
1174template <class _R>
1175void
1176promise<_R>::set_exception_at_thread_exit(exception_ptr __p)
1177{
1178 if (__state_ == nullptr)
1179 throw future_error(make_error_code(future_errc::no_state));
1180 __state_->set_exception_at_thread_exit(__p);
1181}
1182
1183// promise<R&>
1184
1185template <class _R>
1186class promise<_R&>
1187{
1188 __assoc_state<_R&>* __state_;
1189public:
1190 promise();
1191 template <class _Allocator>
1192 promise(allocator_arg_t, const _Allocator& __a);
1193#ifdef _LIBCPP_MOVE
1194 promise(promise&& __rhs)
1195 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
1196 promise(const promise& __rhs) = delete;
1197#else // _LIBCPP_MOVE
1198private:
1199 promise(const promise& __rhs);
1200public:
1201#endif // _LIBCPP_MOVE
1202 ~promise();
1203
1204 // assignment
1205#ifdef _LIBCPP_MOVE
1206 promise& operator=(promise&& __rhs)
1207 {
1208 promise(std::move(__rhs)).swap(*this);
1209 return *this;
1210 }
1211 promise& operator=(const promise& __rhs) = delete;
1212#else // _LIBCPP_MOVE
1213private:
1214 promise& operator=(const promise& __rhs);
1215public:
1216#endif // _LIBCPP_MOVE
1217 void swap(promise& __rhs) {_STD::swap(__state_, __rhs.__state_);}
1218
1219 // retrieving the result
1220 future<_R&> get_future();
1221
1222 // setting the result
1223 void set_value(_R& __r);
1224 void set_exception(exception_ptr __p);
1225
1226 // setting the result with deferred notification
1227 void set_value_at_thread_exit(_R&);
1228 void set_exception_at_thread_exit(exception_ptr __p);
1229};
1230
1231template <class _R>
1232promise<_R&>::promise()
1233 : __state_(new __assoc_state<_R&>)
1234{
1235}
1236
1237template <class _R>
1238template <class _Alloc>
1239promise<_R&>::promise(allocator_arg_t, const _Alloc& __a0)
1240{
1241 typedef typename _Alloc::template rebind<__assoc_state_alloc<_R&, _Alloc> >::other _A2;
1242 typedef __allocator_destructor<_A2> _D2;
1243 _A2 __a(__a0);
1244 unique_ptr<__assoc_state_alloc<_R&, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
1245 ::new(__hold.get()) __assoc_state_alloc<_R&, _Alloc>(__a0);
1246 __state_ = __hold.release();
1247}
1248
1249template <class _R>
1250promise<_R&>::~promise()
1251{
1252 if (__state_)
1253 {
1254 if (!__state_->__has_value() && __state_->use_count() > 1)
1255 __state_->set_exception(make_exception_ptr(
1256 future_error(make_error_code(future_errc::broken_promise))
1257 ));
1258 __state_->__release_shared();
1259 }
1260}
1261
1262template <class _R>
1263future<_R&>
1264promise<_R&>::get_future()
1265{
1266 if (__state_ == nullptr)
1267 throw future_error(make_error_code(future_errc::no_state));
1268 return future<_R&>(__state_);
1269}
1270
1271template <class _R>
1272void
1273promise<_R&>::set_value(_R& __r)
1274{
1275 if (__state_ == nullptr)
1276 throw future_error(make_error_code(future_errc::no_state));
1277 __state_->set_value(__r);
1278}
1279
1280template <class _R>
1281void
1282promise<_R&>::set_exception(exception_ptr __p)
1283{
1284 if (__state_ == nullptr)
1285 throw future_error(make_error_code(future_errc::no_state));
1286 __state_->set_exception(__p);
1287}
1288
1289template <class _R>
1290void
1291promise<_R&>::set_value_at_thread_exit(_R& __r)
1292{
1293 if (__state_ == nullptr)
1294 throw future_error(make_error_code(future_errc::no_state));
1295 __state_->set_value_at_thread_exit(__r);
1296}
1297
1298template <class _R>
1299void
1300promise<_R&>::set_exception_at_thread_exit(exception_ptr __p)
1301{
1302 if (__state_ == nullptr)
1303 throw future_error(make_error_code(future_errc::no_state));
1304 __state_->set_exception_at_thread_exit(__p);
1305}
1306
1307// promise<void>
1308
1309template <>
1310class promise<void>
1311{
1312 __assoc_sub_state* __state_;
1313public:
1314 promise();
1315 template <class _Allocator>
1316 promise(allocator_arg_t, const _Allocator& __a);
1317#ifdef _LIBCPP_MOVE
1318 promise(promise&& __rhs)
1319 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
1320 promise(const promise& __rhs) = delete;
1321#else // _LIBCPP_MOVE
1322private:
1323 promise(const promise& __rhs);
1324public:
1325#endif // _LIBCPP_MOVE
1326 ~promise();
1327
1328 // assignment
1329#ifdef _LIBCPP_MOVE
1330 promise& operator=(promise&& __rhs)
1331 {
1332 promise(std::move(__rhs)).swap(*this);
1333 return *this;
1334 }
1335 promise& operator=(const promise& __rhs) = delete;
1336#else // _LIBCPP_MOVE
1337private:
1338 promise& operator=(const promise& __rhs);
1339public:
1340#endif // _LIBCPP_MOVE
1341 void swap(promise& __rhs) {_STD::swap(__state_, __rhs.__state_);}
1342
1343 // retrieving the result
1344 future<void> get_future();
1345
1346 // setting the result
1347 void set_value();
1348 void set_exception(exception_ptr __p);
1349
1350 // setting the result with deferred notification
1351 void set_value_at_thread_exit();
1352 void set_exception_at_thread_exit(exception_ptr __p);
1353};
1354
1355template <class _Alloc>
1356promise<void>::promise(allocator_arg_t, const _Alloc& __a0)
1357{
1358 typedef typename _Alloc::template rebind<__assoc_sub_state_alloc<_Alloc> >::other _A2;
1359 typedef __allocator_destructor<_A2> _D2;
1360 _A2 __a(__a0);
1361 unique_ptr<__assoc_sub_state_alloc<_Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
1362 ::new(__hold.get()) __assoc_sub_state_alloc<_Alloc>(__a0);
1363 __state_ = __hold.release();
1364}
1365
1366template <class _R>
1367inline _LIBCPP_INLINE_VISIBILITY
1368void
1369swap(promise<_R>& __x, promise<_R>& __y)
1370{
1371 __x.swap(__y);
1372}
1373
1374template <class _R, class _Alloc>
1375 struct uses_allocator<promise<_R>, _Alloc> : public true_type {};
1376
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001377_LIBCPP_END_NAMESPACE_STD
1378
1379#endif // _LIBCPP_FUTURE