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