blob: a8b02a6d63c8fc580b7a5a30f0428363b50dbf2e [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
579template <class _R>
580class __assoc_state
581 : public __assoc_sub_state
582{
583 typedef __assoc_sub_state base;
584 typedef typename aligned_storage<sizeof(_R), alignment_of<_R>::value>::type _U;
585protected:
586 _U __value_;
587
588 virtual void __on_zero_shared();
589public:
590
591 template <class _Arg>
592#ifdef _LIBCPP_MOVE
593 void set_value(_Arg&& __arg);
594#else
595 void set_value(_Arg& __arg);
596#endif
597
598 template <class _Arg>
599#ifdef _LIBCPP_MOVE
600 void set_value_at_thread_exit(_Arg&& __arg);
601#else
602 void set_value_at_thread_exit(_Arg& __arg);
603#endif
604
605 _R move();
606 typename add_lvalue_reference<_R>::type copy();
607};
608
609template <class _R>
610void
611__assoc_state<_R>::__on_zero_shared()
612{
613 if (this->__state_ & base::__constructed)
614 reinterpret_cast<_R*>(&__value_)->~_R();
615 delete this;
616}
617
618template <class _R>
619template <class _Arg>
620void
621#ifdef _LIBCPP_MOVE
622__assoc_state<_R>::set_value(_Arg&& __arg)
623#else
624__assoc_state<_R>::set_value(_Arg& __arg)
625#endif
626{
627 unique_lock<mutex> __lk(this->__mut_);
628 if (this->__has_value())
629 throw future_error(make_error_code(future_errc::promise_already_satisfied));
630 ::new(&__value_) _R(_STD::forward<_Arg>(__arg));
631 this->__state_ |= base::__constructed | base::ready;
632 __lk.unlock();
633 __cv_.notify_all();
634}
635
636template <class _R>
637template <class _Arg>
638void
639#ifdef _LIBCPP_MOVE
640__assoc_state<_R>::set_value_at_thread_exit(_Arg&& __arg)
641#else
642__assoc_state<_R>::set_value_at_thread_exit(_Arg& __arg)
643#endif
644{
645 unique_lock<mutex> __lk(this->__mut_);
646 if (this->__has_value())
647 throw future_error(make_error_code(future_errc::promise_already_satisfied));
648 ::new(&__value_) _R(_STD::forward<_Arg>(__arg));
649 this->__state_ |= base::__constructed;
650 __thread_local_data->__make_ready_at_thread_exit(this);
651 __lk.unlock();
652}
653
654template <class _R>
655_R
656__assoc_state<_R>::move()
657{
658 unique_lock<mutex> __lk(this->__mut_);
659 while (!this->__is_ready())
660 this->__cv_.wait(__lk);
661 if (this->__exception_ != nullptr)
662 rethrow_exception(this->__exception_);
663 return _STD::move(*reinterpret_cast<_R*>(&__value_));
664}
665
666template <class _R>
667typename add_lvalue_reference<_R>::type
668__assoc_state<_R>::copy()
669{
670 unique_lock<mutex> __lk(this->__mut_);
671 while (!this->__is_ready())
672 this->__cv_.wait(__lk);
673 if (this->__exception_ != nullptr)
674 rethrow_exception(this->__exception_);
675 return *reinterpret_cast<_R*>(&__value_);
676}
677
678template <class _R, class _Alloc>
679class __assoc_state_alloc
680 : public __assoc_state<_R>
681{
682 typedef __assoc_state<_R> base;
683 _Alloc __alloc_;
684
685 virtual void __on_zero_shared();
686public:
687 explicit __assoc_state_alloc(const _Alloc& __a)
688 : __alloc_(__a) {}
689};
690
691template <class _R, class _Alloc>
692void
693__assoc_state_alloc<_R, _Alloc>::__on_zero_shared()
694{
695 if (this->__state_ & base::__constructed)
696 reinterpret_cast<_R*>(&this->__value_)->~_R();
697 typename _Alloc::template rebind<__assoc_state_alloc>::other __a(__alloc_);
698 this->~__assoc_state_alloc();
699 __a.deallocate(this, 1);
700}
701
702template <class _Alloc>
703class __assoc_sub_state_alloc
704 : public __assoc_sub_state
705{
706 typedef __assoc_sub_state base;
707 _Alloc __alloc_;
708
709 virtual void __on_zero_shared();
710public:
711 explicit __assoc_sub_state_alloc(const _Alloc& __a)
712 : __alloc_(__a) {}
713};
714
715template <class _Alloc>
716void
717__assoc_sub_state_alloc<_Alloc>::__on_zero_shared()
718{
719 this->~base();
720 typename _Alloc::template rebind<__assoc_state_alloc>::other __a(__alloc_);
721 this->~__assoc_sub_state_alloc();
722 __a.deallocate(this, 1);
723}
724
725template <class> class promise;
726
727// future
728
729template <class _R>
730class future
731{
732 __assoc_state<_R>* __state_;
733
734 explicit future(__assoc_state<_R>* __state);
735
736 template <class> friend class promise;
737public:
738 future() : __state_(nullptr) {}
739#ifdef _LIBCPP_MOVE
740 future(future&& __rhs)
741 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
742 future(const future&) = delete;
743 future& operator=(const future&) = delete;
744 future& operator=(future&& __rhs)
745 {
746 future(std::move(__rhs)).swap(*this);
747 return *this;
748 }
749#else // _LIBCPP_MOVE
750private:
751 future(const future&);
752 future& operator=(const future&);
753public:
754#endif // _LIBCPP_MOVE
755 ~future();
756
757 // retrieving the value
758 _R get();
759
760 void swap(future& __rhs) {_STD::swap(__state_, __rhs.__state_);}
761
762 // functions to check state
763 bool valid() const {return __state_ != nullptr;}
764
765 void wait() const {__state_->wait();}
766 template <class _Rep, class _Period>
767 future_status
768 wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
769 {return __state_->wait_for(__rel_time);}
770 template <class _Clock, class _Duration>
771 future_status
772 wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
773 {return __state_->wait_until(__abs_time);}
774};
775
776template <class _R>
777future<_R>::future(__assoc_state<_R>* __state)
778 : __state_(__state)
779{
780 if (__state_->__has_future_attached())
781 throw future_error(make_error_code(future_errc::future_already_retrieved));
782 __state_->__add_shared();
783}
784
785template <class _R>
786future<_R>::~future()
787{
788 if (__state_)
789 __state_->__release_shared();
790}
791
792template <class _R>
793_R
794future<_R>::get()
795{
796 __assoc_state<_R>* __s = __state_;
797 __state_ = nullptr;
798 return __s->move();
799}
800
801template <class _R>
802class future<_R&>
803{
804 __assoc_state<_R&>* __state_;
805
806 explicit future(__assoc_state<_R&>* __state);
807
808 template <class> friend class promise;
809public:
810 future() : __state_(nullptr) {}
811#ifdef _LIBCPP_MOVE
812 future(future&& __rhs)
813 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
814 future(const future&) = delete;
815 future& operator=(const future&) = delete;
816 future& operator=(future&& __rhs)
817 {
818 future(std::move(__rhs)).swap(*this);
819 return *this;
820 }
821#else // _LIBCPP_MOVE
822private:
823 future(const future&);
824 future& operator=(const future&);
825public:
826#endif // _LIBCPP_MOVE
827 ~future();
828
829 // retrieving the value
830 _R& get();
831
832 void swap(future& __rhs) {_STD::swap(__state_, __rhs.__state_);}
833
834 // functions to check state
835 bool valid() const {return __state_ != nullptr;}
836
837 void wait() const {__state_->wait();}
838 template <class _Rep, class _Period>
839 future_status
840 wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
841 {return __state_->wait_for(__rel_time);}
842 template <class _Clock, class _Duration>
843 future_status
844 wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
845 {return __state_->wait_until(__abs_time);}
846};
847
848template <class _R>
849future<_R&>::future(__assoc_state<_R&>* __state)
850 : __state_(__state)
851{
852 if (__state_->__has_future_attached())
853 throw future_error(make_error_code(future_errc::future_already_retrieved));
854 __state_->__add_shared();
855}
856
857template <class _R>
858future<_R&>::~future()
859{
860 if (__state_)
861 __state_->__release_shared();
862}
863
864template <class _R>
865_R&
866future<_R&>::get()
867{
868 __assoc_state<_R>* __s = __state_;
869 __state_ = nullptr;
870 return __s->copy();
871}
872
873template <>
874class future<void>
875{
876 __assoc_sub_state* __state_;
877
878 explicit future(__assoc_sub_state* __state);
879
880 template <class> friend class promise;
881public:
882 future() : __state_(nullptr) {}
883#ifdef _LIBCPP_MOVE
884 future(future&& __rhs)
885 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
886 future(const future&) = delete;
887 future& operator=(const future&) = delete;
888 future& operator=(future&& __rhs)
889 {
890 future(std::move(__rhs)).swap(*this);
891 return *this;
892 }
893#else // _LIBCPP_MOVE
894private:
895 future(const future&);
896 future& operator=(const future&);
897public:
898#endif // _LIBCPP_MOVE
899 ~future();
900
901 // retrieving the value
902 void get();
903
904 void swap(future& __rhs) {_STD::swap(__state_, __rhs.__state_);}
905
906 // functions to check state
907 bool valid() const {return __state_ != nullptr;}
908
909 void wait() const {__state_->wait();}
910 template <class _Rep, class _Period>
911 future_status
912 wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
913 {return __state_->wait_for(__rel_time);}
914 template <class _Clock, class _Duration>
915 future_status
916 wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
917 {return __state_->wait_until(__abs_time);}
918};
919
920// promise<R>
921
922template <class _R>
923class promise
924{
925 __assoc_state<_R>* __state_;
926public:
927 promise();
928 template <class _Alloc>
929 promise(allocator_arg_t, const _Alloc& __a);
930#ifdef _LIBCPP_MOVE
931 promise(promise&& __rhs)
932 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
933 promise(const promise& __rhs) = delete;
934#else // _LIBCPP_MOVE
935private:
936 promise(const promise& __rhs);
937public:
938#endif // _LIBCPP_MOVE
939 ~promise();
940
941 // assignment
942#ifdef _LIBCPP_MOVE
943 promise& operator=(promise&& __rhs)
944 {
945 promise(std::move(__rhs)).swap(*this);
946 return *this;
947 }
948 promise& operator=(const promise& __rhs) = delete;
949#else // _LIBCPP_MOVE
950private:
951 promise& operator=(const promise& __rhs);
952public:
953#endif // _LIBCPP_MOVE
954 void swap(promise& __rhs) {_STD::swap(__state_, __rhs.__state_);}
955
956 // retrieving the result
957 future<_R> get_future();
958
959 // setting the result
960 void set_value(const _R& __r);
961#ifdef _LIBCPP_MOVE
962 void set_value(_R&& __r);
963#endif
964 void set_exception(exception_ptr __p);
965
966 // setting the result with deferred notification
967 void set_value_at_thread_exit(const _R& __r);
968#ifdef _LIBCPP_MOVE
969 void set_value_at_thread_exit(_R&& __r);
970#endif
971 void set_exception_at_thread_exit(exception_ptr __p);
972};
973
974template <class _R>
975promise<_R>::promise()
976 : __state_(new __assoc_state<_R>)
977{
978}
979
980template <class _R>
981template <class _Alloc>
982promise<_R>::promise(allocator_arg_t, const _Alloc& __a0)
983{
984 typedef typename _Alloc::template rebind<__assoc_state_alloc<_R, _Alloc> >::other _A2;
985 typedef __allocator_destructor<_A2> _D2;
986 _A2 __a(__a0);
987 unique_ptr<__assoc_state_alloc<_R, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
988 ::new(__hold.get()) __assoc_state_alloc<_R, _Alloc>(__a0);
989 __state_ = __hold.release();
990}
991
992template <class _R>
993promise<_R>::~promise()
994{
995 if (__state_)
996 {
997 if (!__state_->__has_value() && __state_->use_count() > 1)
998 __state_->set_exception(make_exception_ptr(
999 future_error(make_error_code(future_errc::broken_promise))
1000 ));
1001 __state_->__release_shared();
1002 }
1003}
1004
1005template <class _R>
1006future<_R>
1007promise<_R>::get_future()
1008{
1009 if (__state_ == nullptr)
1010 throw future_error(make_error_code(future_errc::no_state));
1011 return future<_R>(__state_);
1012}
1013
1014template <class _R>
1015void
1016promise<_R>::set_value(const _R& __r)
1017{
1018 if (__state_ == nullptr)
1019 throw future_error(make_error_code(future_errc::no_state));
1020 __state_->set_value(__r);
1021}
1022
1023#ifdef _LIBCPP_MOVE
1024
1025template <class _R>
1026void
1027promise<_R>::set_value(_R&& __r)
1028{
1029 if (__state_ == nullptr)
1030 throw future_error(make_error_code(future_errc::no_state));
1031 __state_->set_value(_STD::move(__r));
1032}
1033
1034#endif // _LIBCPP_MOVE
1035
1036template <class _R>
1037void
1038promise<_R>::set_exception(exception_ptr __p)
1039{
1040 if (__state_ == nullptr)
1041 throw future_error(make_error_code(future_errc::no_state));
1042 __state_->set_exception(__p);
1043}
1044
1045template <class _R>
1046void
1047promise<_R>::set_value_at_thread_exit(const _R& __r)
1048{
1049 if (__state_ == nullptr)
1050 throw future_error(make_error_code(future_errc::no_state));
1051 __state_->set_value_at_thread_exit(__r);
1052}
1053
1054#ifdef _LIBCPP_MOVE
1055
1056template <class _R>
1057void
1058promise<_R>::set_value_at_thread_exit(_R&& __r)
1059{
1060 if (__state_ == nullptr)
1061 throw future_error(make_error_code(future_errc::no_state));
1062 __state_->set_value_at_thread_exit(_STD::move(__r));
1063}
1064
1065#endif // _LIBCPP_MOVE
1066
1067template <class _R>
1068void
1069promise<_R>::set_exception_at_thread_exit(exception_ptr __p)
1070{
1071 if (__state_ == nullptr)
1072 throw future_error(make_error_code(future_errc::no_state));
1073 __state_->set_exception_at_thread_exit(__p);
1074}
1075
1076// promise<R&>
1077
1078template <class _R>
1079class promise<_R&>
1080{
1081 __assoc_state<_R&>* __state_;
1082public:
1083 promise();
1084 template <class _Allocator>
1085 promise(allocator_arg_t, const _Allocator& __a);
1086#ifdef _LIBCPP_MOVE
1087 promise(promise&& __rhs)
1088 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
1089 promise(const promise& __rhs) = delete;
1090#else // _LIBCPP_MOVE
1091private:
1092 promise(const promise& __rhs);
1093public:
1094#endif // _LIBCPP_MOVE
1095 ~promise();
1096
1097 // assignment
1098#ifdef _LIBCPP_MOVE
1099 promise& operator=(promise&& __rhs)
1100 {
1101 promise(std::move(__rhs)).swap(*this);
1102 return *this;
1103 }
1104 promise& operator=(const promise& __rhs) = delete;
1105#else // _LIBCPP_MOVE
1106private:
1107 promise& operator=(const promise& __rhs);
1108public:
1109#endif // _LIBCPP_MOVE
1110 void swap(promise& __rhs) {_STD::swap(__state_, __rhs.__state_);}
1111
1112 // retrieving the result
1113 future<_R&> get_future();
1114
1115 // setting the result
1116 void set_value(_R& __r);
1117 void set_exception(exception_ptr __p);
1118
1119 // setting the result with deferred notification
1120 void set_value_at_thread_exit(_R&);
1121 void set_exception_at_thread_exit(exception_ptr __p);
1122};
1123
1124template <class _R>
1125promise<_R&>::promise()
1126 : __state_(new __assoc_state<_R&>)
1127{
1128}
1129
1130template <class _R>
1131template <class _Alloc>
1132promise<_R&>::promise(allocator_arg_t, const _Alloc& __a0)
1133{
1134 typedef typename _Alloc::template rebind<__assoc_state_alloc<_R&, _Alloc> >::other _A2;
1135 typedef __allocator_destructor<_A2> _D2;
1136 _A2 __a(__a0);
1137 unique_ptr<__assoc_state_alloc<_R&, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
1138 ::new(__hold.get()) __assoc_state_alloc<_R&, _Alloc>(__a0);
1139 __state_ = __hold.release();
1140}
1141
1142template <class _R>
1143promise<_R&>::~promise()
1144{
1145 if (__state_)
1146 {
1147 if (!__state_->__has_value() && __state_->use_count() > 1)
1148 __state_->set_exception(make_exception_ptr(
1149 future_error(make_error_code(future_errc::broken_promise))
1150 ));
1151 __state_->__release_shared();
1152 }
1153}
1154
1155template <class _R>
1156future<_R&>
1157promise<_R&>::get_future()
1158{
1159 if (__state_ == nullptr)
1160 throw future_error(make_error_code(future_errc::no_state));
1161 return future<_R&>(__state_);
1162}
1163
1164template <class _R>
1165void
1166promise<_R&>::set_value(_R& __r)
1167{
1168 if (__state_ == nullptr)
1169 throw future_error(make_error_code(future_errc::no_state));
1170 __state_->set_value(__r);
1171}
1172
1173template <class _R>
1174void
1175promise<_R&>::set_exception(exception_ptr __p)
1176{
1177 if (__state_ == nullptr)
1178 throw future_error(make_error_code(future_errc::no_state));
1179 __state_->set_exception(__p);
1180}
1181
1182template <class _R>
1183void
1184promise<_R&>::set_value_at_thread_exit(_R& __r)
1185{
1186 if (__state_ == nullptr)
1187 throw future_error(make_error_code(future_errc::no_state));
1188 __state_->set_value_at_thread_exit(__r);
1189}
1190
1191template <class _R>
1192void
1193promise<_R&>::set_exception_at_thread_exit(exception_ptr __p)
1194{
1195 if (__state_ == nullptr)
1196 throw future_error(make_error_code(future_errc::no_state));
1197 __state_->set_exception_at_thread_exit(__p);
1198}
1199
1200// promise<void>
1201
1202template <>
1203class promise<void>
1204{
1205 __assoc_sub_state* __state_;
1206public:
1207 promise();
1208 template <class _Allocator>
1209 promise(allocator_arg_t, const _Allocator& __a);
1210#ifdef _LIBCPP_MOVE
1211 promise(promise&& __rhs)
1212 : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
1213 promise(const promise& __rhs) = delete;
1214#else // _LIBCPP_MOVE
1215private:
1216 promise(const promise& __rhs);
1217public:
1218#endif // _LIBCPP_MOVE
1219 ~promise();
1220
1221 // assignment
1222#ifdef _LIBCPP_MOVE
1223 promise& operator=(promise&& __rhs)
1224 {
1225 promise(std::move(__rhs)).swap(*this);
1226 return *this;
1227 }
1228 promise& operator=(const promise& __rhs) = delete;
1229#else // _LIBCPP_MOVE
1230private:
1231 promise& operator=(const promise& __rhs);
1232public:
1233#endif // _LIBCPP_MOVE
1234 void swap(promise& __rhs) {_STD::swap(__state_, __rhs.__state_);}
1235
1236 // retrieving the result
1237 future<void> get_future();
1238
1239 // setting the result
1240 void set_value();
1241 void set_exception(exception_ptr __p);
1242
1243 // setting the result with deferred notification
1244 void set_value_at_thread_exit();
1245 void set_exception_at_thread_exit(exception_ptr __p);
1246};
1247
1248template <class _Alloc>
1249promise<void>::promise(allocator_arg_t, const _Alloc& __a0)
1250{
1251 typedef typename _Alloc::template rebind<__assoc_sub_state_alloc<_Alloc> >::other _A2;
1252 typedef __allocator_destructor<_A2> _D2;
1253 _A2 __a(__a0);
1254 unique_ptr<__assoc_sub_state_alloc<_Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
1255 ::new(__hold.get()) __assoc_sub_state_alloc<_Alloc>(__a0);
1256 __state_ = __hold.release();
1257}
1258
1259template <class _R>
1260inline _LIBCPP_INLINE_VISIBILITY
1261void
1262swap(promise<_R>& __x, promise<_R>& __y)
1263{
1264 __x.swap(__y);
1265}
1266
1267template <class _R, class _Alloc>
1268 struct uses_allocator<promise<_R>, _Alloc> : public true_type {};
1269
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001270_LIBCPP_END_NAMESPACE_STD
1271
1272#endif // _LIBCPP_FUTURE