xref: /llvm-project-15.0.7/libcxx/src/future.cpp (revision 3aa229f7)
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 _NOEXCEPT;
20     virtual string message(int ev) const;
21 };
22 
23 const char*
24 __future_error_category::name() const _NOEXCEPT
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 future_error::~future_error() _NOEXCEPT
63 {
64 }
65 
66 void
67 __assoc_sub_state::__on_zero_shared() _NOEXCEPT
68 {
69     delete this;
70 }
71 
72 void
73 __assoc_sub_state::set_value()
74 {
75     unique_lock<mutex> __lk(__mut_);
76     if (__has_value())
77         throw future_error(make_error_code(future_errc::promise_already_satisfied));
78     __state_ |= __constructed | ready;
79     __lk.unlock();
80     __cv_.notify_all();
81 }
82 
83 void
84 __assoc_sub_state::set_value_at_thread_exit()
85 {
86     unique_lock<mutex> __lk(__mut_);
87     if (__has_value())
88         throw future_error(make_error_code(future_errc::promise_already_satisfied));
89     __state_ |= __constructed;
90     __thread_local_data()->__make_ready_at_thread_exit(this);
91     __lk.unlock();
92 }
93 
94 void
95 __assoc_sub_state::set_exception(exception_ptr __p)
96 {
97     unique_lock<mutex> __lk(__mut_);
98     if (__has_value())
99         throw future_error(make_error_code(future_errc::promise_already_satisfied));
100     __exception_ = __p;
101     __state_ |= ready;
102     __lk.unlock();
103     __cv_.notify_all();
104 }
105 
106 void
107 __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
108 {
109     unique_lock<mutex> __lk(__mut_);
110     if (__has_value())
111         throw future_error(make_error_code(future_errc::promise_already_satisfied));
112     __exception_ = __p;
113     __thread_local_data()->__make_ready_at_thread_exit(this);
114     __lk.unlock();
115 }
116 
117 void
118 __assoc_sub_state::__make_ready()
119 {
120     unique_lock<mutex> __lk(__mut_);
121     __state_ |= ready;
122     __lk.unlock();
123     __cv_.notify_all();
124 }
125 
126 void
127 __assoc_sub_state::copy()
128 {
129     unique_lock<mutex> __lk(__mut_);
130     __sub_wait(__lk);
131     if (__exception_ != nullptr)
132         rethrow_exception(__exception_);
133 }
134 
135 void
136 __assoc_sub_state::wait()
137 {
138     unique_lock<mutex> __lk(__mut_);
139     __sub_wait(__lk);
140 }
141 
142 void
143 __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
144 {
145     if (!__is_ready())
146     {
147         if (__state_ & deferred)
148         {
149             __state_ &= ~deferred;
150             __lk.unlock();
151             __execute();
152         }
153         else
154             while (!__is_ready())
155                 __cv_.wait(__lk);
156     }
157 }
158 
159 void
160 __assoc_sub_state::__execute()
161 {
162     throw future_error(make_error_code(future_errc::no_state));
163 }
164 
165 future<void>::future(__assoc_sub_state* __state)
166     : __state_(__state)
167 {
168     if (__state_->__has_future_attached())
169         throw future_error(make_error_code(future_errc::future_already_retrieved));
170     __state_->__add_shared();
171     __state_->__set_future_attached();
172 }
173 
174 future<void>::~future()
175 {
176     if (__state_)
177         __state_->__release_shared();
178 }
179 
180 void
181 future<void>::get()
182 {
183     unique_ptr<__shared_count, __release_shared_count> __(__state_);
184     __assoc_sub_state* __s = __state_;
185     __state_ = nullptr;
186     __s->copy();
187 }
188 
189 promise<void>::promise()
190     : __state_(new __assoc_sub_state)
191 {
192 }
193 
194 promise<void>::~promise()
195 {
196     if (__state_)
197     {
198         if (!__state_->__has_value() && __state_->use_count() > 1)
199             __state_->set_exception(make_exception_ptr(
200                       future_error(make_error_code(future_errc::broken_promise))
201                                                       ));
202         __state_->__release_shared();
203     }
204 }
205 
206 future<void>
207 promise<void>::get_future()
208 {
209     if (__state_ == nullptr)
210         throw future_error(make_error_code(future_errc::no_state));
211     return future<void>(__state_);
212 }
213 
214 void
215 promise<void>::set_value()
216 {
217     if (__state_ == nullptr)
218         throw future_error(make_error_code(future_errc::no_state));
219     __state_->set_value();
220 }
221 
222 void
223 promise<void>::set_exception(exception_ptr __p)
224 {
225     if (__state_ == nullptr)
226         throw future_error(make_error_code(future_errc::no_state));
227     __state_->set_exception(__p);
228 }
229 
230 void
231 promise<void>::set_value_at_thread_exit()
232 {
233     if (__state_ == nullptr)
234         throw future_error(make_error_code(future_errc::no_state));
235     __state_->set_value_at_thread_exit();
236 }
237 
238 void
239 promise<void>::set_exception_at_thread_exit(exception_ptr __p)
240 {
241     if (__state_ == nullptr)
242         throw future_error(make_error_code(future_errc::no_state));
243     __state_->set_exception_at_thread_exit(__p);
244 }
245 
246 shared_future<void>::~shared_future()
247 {
248     if (__state_)
249         __state_->__release_shared();
250 }
251 
252 shared_future<void>&
253 shared_future<void>::operator=(const shared_future& __rhs)
254 {
255     if (__rhs.__state_)
256         __rhs.__state_->__add_shared();
257     if (__state_)
258         __state_->__release_shared();
259     __state_ = __rhs.__state_;
260     return *this;
261 }
262 
263 _LIBCPP_END_NAMESPACE_STD
264