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