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