xref: /minix3/external/bsd/libc++/dist/libcxx/src/future.cpp (revision 4684ddb6aab0b36791c8099bc705d6140b3d05d0)
1*4684ddb6SLionel Sambuc //===------------------------- future.cpp ---------------------------------===//
2*4684ddb6SLionel Sambuc //
3*4684ddb6SLionel Sambuc //                     The LLVM Compiler Infrastructure
4*4684ddb6SLionel Sambuc //
5*4684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
6*4684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
7*4684ddb6SLionel Sambuc //
8*4684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
9*4684ddb6SLionel Sambuc 
10*4684ddb6SLionel Sambuc #include "future"
11*4684ddb6SLionel Sambuc #include "string"
12*4684ddb6SLionel Sambuc 
13*4684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD
14*4684ddb6SLionel Sambuc 
15*4684ddb6SLionel Sambuc class _LIBCPP_HIDDEN __future_error_category
16*4684ddb6SLionel Sambuc     : public __do_message
17*4684ddb6SLionel Sambuc {
18*4684ddb6SLionel Sambuc public:
19*4684ddb6SLionel Sambuc     virtual const char* name() const _NOEXCEPT;
20*4684ddb6SLionel Sambuc     virtual string message(int ev) const;
21*4684ddb6SLionel Sambuc };
22*4684ddb6SLionel Sambuc 
23*4684ddb6SLionel Sambuc const char*
24*4684ddb6SLionel Sambuc __future_error_category::name() const _NOEXCEPT
25*4684ddb6SLionel Sambuc {
26*4684ddb6SLionel Sambuc     return "future";
27*4684ddb6SLionel Sambuc }
28*4684ddb6SLionel Sambuc 
29*4684ddb6SLionel Sambuc #pragma clang diagnostic push
30*4684ddb6SLionel Sambuc #pragma clang diagnostic ignored "-Wswitch"
31*4684ddb6SLionel Sambuc 
32*4684ddb6SLionel Sambuc string
33*4684ddb6SLionel Sambuc __future_error_category::message(int ev) const
34*4684ddb6SLionel Sambuc {
35*4684ddb6SLionel Sambuc     switch (static_cast<future_errc>(ev))
36*4684ddb6SLionel Sambuc     {
37*4684ddb6SLionel Sambuc     case future_errc(0):  // For backwards compatibility with C++11 (LWG 2056)
38*4684ddb6SLionel Sambuc     case future_errc::broken_promise:
39*4684ddb6SLionel Sambuc         return string("The associated promise has been destructed prior "
40*4684ddb6SLionel Sambuc                       "to the associated state becoming ready.");
41*4684ddb6SLionel Sambuc     case future_errc::future_already_retrieved:
42*4684ddb6SLionel Sambuc         return string("The future has already been retrieved from "
43*4684ddb6SLionel Sambuc                       "the promise or packaged_task.");
44*4684ddb6SLionel Sambuc     case future_errc::promise_already_satisfied:
45*4684ddb6SLionel Sambuc         return string("The state of the promise has already been set.");
46*4684ddb6SLionel Sambuc     case future_errc::no_state:
47*4684ddb6SLionel Sambuc         return string("Operation not permitted on an object without "
48*4684ddb6SLionel Sambuc                       "an associated state.");
49*4684ddb6SLionel Sambuc     }
50*4684ddb6SLionel Sambuc     return string("unspecified future_errc value\n");
51*4684ddb6SLionel Sambuc }
52*4684ddb6SLionel Sambuc 
53*4684ddb6SLionel Sambuc #pragma clang diagnostic pop
54*4684ddb6SLionel Sambuc 
55*4684ddb6SLionel Sambuc const error_category&
56*4684ddb6SLionel Sambuc future_category() _NOEXCEPT
57*4684ddb6SLionel Sambuc {
58*4684ddb6SLionel Sambuc     static __future_error_category __f;
59*4684ddb6SLionel Sambuc     return __f;
60*4684ddb6SLionel Sambuc }
61*4684ddb6SLionel Sambuc 
62*4684ddb6SLionel Sambuc future_error::future_error(error_code __ec)
63*4684ddb6SLionel Sambuc     : logic_error(__ec.message()),
64*4684ddb6SLionel Sambuc       __ec_(__ec)
65*4684ddb6SLionel Sambuc {
66*4684ddb6SLionel Sambuc }
67*4684ddb6SLionel Sambuc 
68*4684ddb6SLionel Sambuc future_error::~future_error() _NOEXCEPT
69*4684ddb6SLionel Sambuc {
70*4684ddb6SLionel Sambuc }
71*4684ddb6SLionel Sambuc 
72*4684ddb6SLionel Sambuc void
73*4684ddb6SLionel Sambuc __assoc_sub_state::__on_zero_shared() _NOEXCEPT
74*4684ddb6SLionel Sambuc {
75*4684ddb6SLionel Sambuc     delete this;
76*4684ddb6SLionel Sambuc }
77*4684ddb6SLionel Sambuc 
78*4684ddb6SLionel Sambuc void
79*4684ddb6SLionel Sambuc __assoc_sub_state::set_value()
80*4684ddb6SLionel Sambuc {
81*4684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
82*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
83*4684ddb6SLionel Sambuc     if (__has_value())
84*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::promise_already_satisfied));
85*4684ddb6SLionel Sambuc #endif
86*4684ddb6SLionel Sambuc     __state_ |= __constructed | ready;
87*4684ddb6SLionel Sambuc     __cv_.notify_all();
88*4684ddb6SLionel Sambuc     __lk.unlock();
89*4684ddb6SLionel Sambuc }
90*4684ddb6SLionel Sambuc 
91*4684ddb6SLionel Sambuc void
92*4684ddb6SLionel Sambuc __assoc_sub_state::set_value_at_thread_exit()
93*4684ddb6SLionel Sambuc {
94*4684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
95*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
96*4684ddb6SLionel Sambuc     if (__has_value())
97*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::promise_already_satisfied));
98*4684ddb6SLionel Sambuc #endif
99*4684ddb6SLionel Sambuc     __state_ |= __constructed;
100*4684ddb6SLionel Sambuc     __thread_local_data()->__make_ready_at_thread_exit(this);
101*4684ddb6SLionel Sambuc     __lk.unlock();
102*4684ddb6SLionel Sambuc }
103*4684ddb6SLionel Sambuc 
104*4684ddb6SLionel Sambuc void
105*4684ddb6SLionel Sambuc __assoc_sub_state::set_exception(exception_ptr __p)
106*4684ddb6SLionel Sambuc {
107*4684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
108*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
109*4684ddb6SLionel Sambuc     if (__has_value())
110*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::promise_already_satisfied));
111*4684ddb6SLionel Sambuc #endif
112*4684ddb6SLionel Sambuc     __exception_ = __p;
113*4684ddb6SLionel Sambuc     __state_ |= ready;
114*4684ddb6SLionel Sambuc     __lk.unlock();
115*4684ddb6SLionel Sambuc     __cv_.notify_all();
116*4684ddb6SLionel Sambuc }
117*4684ddb6SLionel Sambuc 
118*4684ddb6SLionel Sambuc void
119*4684ddb6SLionel Sambuc __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
120*4684ddb6SLionel Sambuc {
121*4684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
122*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
123*4684ddb6SLionel Sambuc     if (__has_value())
124*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::promise_already_satisfied));
125*4684ddb6SLionel Sambuc #endif
126*4684ddb6SLionel Sambuc     __exception_ = __p;
127*4684ddb6SLionel Sambuc     __thread_local_data()->__make_ready_at_thread_exit(this);
128*4684ddb6SLionel Sambuc     __lk.unlock();
129*4684ddb6SLionel Sambuc }
130*4684ddb6SLionel Sambuc 
131*4684ddb6SLionel Sambuc void
132*4684ddb6SLionel Sambuc __assoc_sub_state::__make_ready()
133*4684ddb6SLionel Sambuc {
134*4684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
135*4684ddb6SLionel Sambuc     __state_ |= ready;
136*4684ddb6SLionel Sambuc     __lk.unlock();
137*4684ddb6SLionel Sambuc     __cv_.notify_all();
138*4684ddb6SLionel Sambuc }
139*4684ddb6SLionel Sambuc 
140*4684ddb6SLionel Sambuc void
141*4684ddb6SLionel Sambuc __assoc_sub_state::copy()
142*4684ddb6SLionel Sambuc {
143*4684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
144*4684ddb6SLionel Sambuc     __sub_wait(__lk);
145*4684ddb6SLionel Sambuc     if (__exception_ != nullptr)
146*4684ddb6SLionel Sambuc         rethrow_exception(__exception_);
147*4684ddb6SLionel Sambuc }
148*4684ddb6SLionel Sambuc 
149*4684ddb6SLionel Sambuc void
150*4684ddb6SLionel Sambuc __assoc_sub_state::wait()
151*4684ddb6SLionel Sambuc {
152*4684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
153*4684ddb6SLionel Sambuc     __sub_wait(__lk);
154*4684ddb6SLionel Sambuc }
155*4684ddb6SLionel Sambuc 
156*4684ddb6SLionel Sambuc void
157*4684ddb6SLionel Sambuc __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
158*4684ddb6SLionel Sambuc {
159*4684ddb6SLionel Sambuc     if (!__is_ready())
160*4684ddb6SLionel Sambuc     {
161*4684ddb6SLionel Sambuc         if (__state_ & static_cast<unsigned>(deferred))
162*4684ddb6SLionel Sambuc         {
163*4684ddb6SLionel Sambuc             __state_ &= ~static_cast<unsigned>(deferred);
164*4684ddb6SLionel Sambuc             __lk.unlock();
165*4684ddb6SLionel Sambuc             __execute();
166*4684ddb6SLionel Sambuc         }
167*4684ddb6SLionel Sambuc         else
168*4684ddb6SLionel Sambuc             while (!__is_ready())
169*4684ddb6SLionel Sambuc                 __cv_.wait(__lk);
170*4684ddb6SLionel Sambuc     }
171*4684ddb6SLionel Sambuc }
172*4684ddb6SLionel Sambuc 
173*4684ddb6SLionel Sambuc void
174*4684ddb6SLionel Sambuc __assoc_sub_state::__execute()
175*4684ddb6SLionel Sambuc {
176*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
177*4684ddb6SLionel Sambuc     throw future_error(make_error_code(future_errc::no_state));
178*4684ddb6SLionel Sambuc #endif
179*4684ddb6SLionel Sambuc }
180*4684ddb6SLionel Sambuc 
181*4684ddb6SLionel Sambuc future<void>::future(__assoc_sub_state* __state)
182*4684ddb6SLionel Sambuc     : __state_(__state)
183*4684ddb6SLionel Sambuc {
184*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
185*4684ddb6SLionel Sambuc     if (__state_->__has_future_attached())
186*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::future_already_retrieved));
187*4684ddb6SLionel Sambuc #endif
188*4684ddb6SLionel Sambuc     __state_->__add_shared();
189*4684ddb6SLionel Sambuc     __state_->__set_future_attached();
190*4684ddb6SLionel Sambuc }
191*4684ddb6SLionel Sambuc 
192*4684ddb6SLionel Sambuc future<void>::~future()
193*4684ddb6SLionel Sambuc {
194*4684ddb6SLionel Sambuc     if (__state_)
195*4684ddb6SLionel Sambuc         __state_->__release_shared();
196*4684ddb6SLionel Sambuc }
197*4684ddb6SLionel Sambuc 
198*4684ddb6SLionel Sambuc void
199*4684ddb6SLionel Sambuc future<void>::get()
200*4684ddb6SLionel Sambuc {
201*4684ddb6SLionel Sambuc     unique_ptr<__shared_count, __release_shared_count> __(__state_);
202*4684ddb6SLionel Sambuc     __assoc_sub_state* __s = __state_;
203*4684ddb6SLionel Sambuc     __state_ = nullptr;
204*4684ddb6SLionel Sambuc     __s->copy();
205*4684ddb6SLionel Sambuc }
206*4684ddb6SLionel Sambuc 
207*4684ddb6SLionel Sambuc promise<void>::promise()
208*4684ddb6SLionel Sambuc     : __state_(new __assoc_sub_state)
209*4684ddb6SLionel Sambuc {
210*4684ddb6SLionel Sambuc }
211*4684ddb6SLionel Sambuc 
212*4684ddb6SLionel Sambuc promise<void>::~promise()
213*4684ddb6SLionel Sambuc {
214*4684ddb6SLionel Sambuc     if (__state_)
215*4684ddb6SLionel Sambuc     {
216*4684ddb6SLionel Sambuc         if (!__state_->__has_value() && __state_->use_count() > 1)
217*4684ddb6SLionel Sambuc             __state_->set_exception(make_exception_ptr(
218*4684ddb6SLionel Sambuc                       future_error(make_error_code(future_errc::broken_promise))
219*4684ddb6SLionel Sambuc                                                       ));
220*4684ddb6SLionel Sambuc         __state_->__release_shared();
221*4684ddb6SLionel Sambuc     }
222*4684ddb6SLionel Sambuc }
223*4684ddb6SLionel Sambuc 
224*4684ddb6SLionel Sambuc future<void>
225*4684ddb6SLionel Sambuc promise<void>::get_future()
226*4684ddb6SLionel Sambuc {
227*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
228*4684ddb6SLionel Sambuc     if (__state_ == nullptr)
229*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
230*4684ddb6SLionel Sambuc #endif
231*4684ddb6SLionel Sambuc     return future<void>(__state_);
232*4684ddb6SLionel Sambuc }
233*4684ddb6SLionel Sambuc 
234*4684ddb6SLionel Sambuc void
235*4684ddb6SLionel Sambuc promise<void>::set_value()
236*4684ddb6SLionel Sambuc {
237*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
238*4684ddb6SLionel Sambuc     if (__state_ == nullptr)
239*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
240*4684ddb6SLionel Sambuc #endif
241*4684ddb6SLionel Sambuc     __state_->set_value();
242*4684ddb6SLionel Sambuc }
243*4684ddb6SLionel Sambuc 
244*4684ddb6SLionel Sambuc void
245*4684ddb6SLionel Sambuc promise<void>::set_exception(exception_ptr __p)
246*4684ddb6SLionel Sambuc {
247*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
248*4684ddb6SLionel Sambuc     if (__state_ == nullptr)
249*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
250*4684ddb6SLionel Sambuc #endif
251*4684ddb6SLionel Sambuc     __state_->set_exception(__p);
252*4684ddb6SLionel Sambuc }
253*4684ddb6SLionel Sambuc 
254*4684ddb6SLionel Sambuc void
255*4684ddb6SLionel Sambuc promise<void>::set_value_at_thread_exit()
256*4684ddb6SLionel Sambuc {
257*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
258*4684ddb6SLionel Sambuc     if (__state_ == nullptr)
259*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
260*4684ddb6SLionel Sambuc #endif
261*4684ddb6SLionel Sambuc     __state_->set_value_at_thread_exit();
262*4684ddb6SLionel Sambuc }
263*4684ddb6SLionel Sambuc 
264*4684ddb6SLionel Sambuc void
265*4684ddb6SLionel Sambuc promise<void>::set_exception_at_thread_exit(exception_ptr __p)
266*4684ddb6SLionel Sambuc {
267*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
268*4684ddb6SLionel Sambuc     if (__state_ == nullptr)
269*4684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
270*4684ddb6SLionel Sambuc #endif
271*4684ddb6SLionel Sambuc     __state_->set_exception_at_thread_exit(__p);
272*4684ddb6SLionel Sambuc }
273*4684ddb6SLionel Sambuc 
274*4684ddb6SLionel Sambuc shared_future<void>::~shared_future()
275*4684ddb6SLionel Sambuc {
276*4684ddb6SLionel Sambuc     if (__state_)
277*4684ddb6SLionel Sambuc         __state_->__release_shared();
278*4684ddb6SLionel Sambuc }
279*4684ddb6SLionel Sambuc 
280*4684ddb6SLionel Sambuc shared_future<void>&
281*4684ddb6SLionel Sambuc shared_future<void>::operator=(const shared_future& __rhs)
282*4684ddb6SLionel Sambuc {
283*4684ddb6SLionel Sambuc     if (__rhs.__state_)
284*4684ddb6SLionel Sambuc         __rhs.__state_->__add_shared();
285*4684ddb6SLionel Sambuc     if (__state_)
286*4684ddb6SLionel Sambuc         __state_->__release_shared();
287*4684ddb6SLionel Sambuc     __state_ = __rhs.__state_;
288*4684ddb6SLionel Sambuc     return *this;
289*4684ddb6SLionel Sambuc }
290*4684ddb6SLionel Sambuc 
291*4684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD
292