blob: cdaa93827533d99ec05ec6e7b4b2848ea31676c0 [file] [log] [blame]
Louis Dionne9bd93882021-11-17 16:25:01 -05001//===----------------------------------------------------------------------===//
Howard Hinnant96803d92010-08-25 17:32:05 +00002//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnant96803d92010-08-25 17:32:05 +00006//
7//===----------------------------------------------------------------------===//
8
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -05009#include <__config>
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +000010
11#ifndef _LIBCPP_HAS_NO_THREADS
12
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -050013#include <future>
14#include <string>
Howard Hinnant96803d92010-08-25 17:32:05 +000015
16_LIBCPP_BEGIN_NAMESPACE_STD
17
18class _LIBCPP_HIDDEN __future_error_category
19 : public __do_message
20{
21public:
Louis Dionne65358e12021-03-01 12:09:45 -050022 virtual const char* name() const noexcept;
Howard Hinnant96803d92010-08-25 17:32:05 +000023 virtual string message(int ev) const;
24};
25
26const char*
Louis Dionne65358e12021-03-01 12:09:45 -050027__future_error_category::name() const noexcept
Howard Hinnant96803d92010-08-25 17:32:05 +000028{
29 return "future";
30}
31
Nikolas Klauser41c59762022-02-14 18:52:28 +010032_LIBCPP_DIAGNOSTIC_PUSH
33_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")
34_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")
Howard Hinnantf2fd64d2013-09-14 18:20:10 +000035
Howard Hinnant96803d92010-08-25 17:32:05 +000036string
37__future_error_category::message(int ev) const
38{
Howard Hinnant5afe2522012-02-02 20:31:36 +000039 switch (static_cast<future_errc>(ev))
Howard Hinnant96803d92010-08-25 17:32:05 +000040 {
Howard Hinnantf2fd64d2013-09-14 18:20:10 +000041 case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)
Howard Hinnant96803d92010-08-25 17:32:05 +000042 case future_errc::broken_promise:
43 return string("The associated promise has been destructed prior "
44 "to the associated state becoming ready.");
45 case future_errc::future_already_retrieved:
46 return string("The future has already been retrieved from "
47 "the promise or packaged_task.");
48 case future_errc::promise_already_satisfied:
49 return string("The state of the promise has already been set.");
50 case future_errc::no_state:
51 return string("Operation not permitted on an object without "
52 "an associated state.");
53 }
54 return string("unspecified future_errc value\n");
55}
56
Nikolas Klauser41c59762022-02-14 18:52:28 +010057_LIBCPP_DIAGNOSTIC_POP
Howard Hinnantf2fd64d2013-09-14 18:20:10 +000058
Howard Hinnant96803d92010-08-25 17:32:05 +000059const error_category&
Louis Dionne65358e12021-03-01 12:09:45 -050060future_category() noexcept
Howard Hinnant96803d92010-08-25 17:32:05 +000061{
62 static __future_error_category __f;
63 return __f;
64}
65
66future_error::future_error(error_code __ec)
67 : logic_error(__ec.message()),
68 __ec_(__ec)
69{
70}
71
Louis Dionne65358e12021-03-01 12:09:45 -050072future_error::~future_error() noexcept
Howard Hinnant5e0c5212011-07-08 00:04:40 +000073{
74}
75
Howard Hinnant3820f6b2010-08-27 20:10:19 +000076void
Louis Dionne65358e12021-03-01 12:09:45 -050077__assoc_sub_state::__on_zero_shared() noexcept
Howard Hinnant3820f6b2010-08-27 20:10:19 +000078{
79 delete this;
80}
81
82void
83__assoc_sub_state::set_value()
84{
85 unique_lock<mutex> __lk(__mut_);
86 if (__has_value())
Marshall Clow9ea94bc2018-07-30 23:33:48 +000087 __throw_future_error(future_errc::promise_already_satisfied);
Howard Hinnant3820f6b2010-08-27 20:10:19 +000088 __state_ |= __constructed | ready;
Howard Hinnant3820f6b2010-08-27 20:10:19 +000089 __cv_.notify_all();
90}
91
92void
93__assoc_sub_state::set_value_at_thread_exit()
94{
95 unique_lock<mutex> __lk(__mut_);
96 if (__has_value())
Marshall Clow9ea94bc2018-07-30 23:33:48 +000097 __throw_future_error(future_errc::promise_already_satisfied);
Howard Hinnant3820f6b2010-08-27 20:10:19 +000098 __state_ |= __constructed;
Howard Hinnant15d55052010-10-14 19:18:04 +000099 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000100}
101
102void
103__assoc_sub_state::set_exception(exception_ptr __p)
104{
105 unique_lock<mutex> __lk(__mut_);
106 if (__has_value())
Marshall Clow9ea94bc2018-07-30 23:33:48 +0000107 __throw_future_error(future_errc::promise_already_satisfied);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000108 __exception_ = __p;
109 __state_ |= ready;
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000110 __cv_.notify_all();
111}
112
113void
114__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
115{
116 unique_lock<mutex> __lk(__mut_);
117 if (__has_value())
Marshall Clow9ea94bc2018-07-30 23:33:48 +0000118 __throw_future_error(future_errc::promise_already_satisfied);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000119 __exception_ = __p;
Howard Hinnant15d55052010-10-14 19:18:04 +0000120 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000121}
122
123void
124__assoc_sub_state::__make_ready()
125{
126 unique_lock<mutex> __lk(__mut_);
127 __state_ |= ready;
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000128 __cv_.notify_all();
129}
130
131void
132__assoc_sub_state::copy()
133{
134 unique_lock<mutex> __lk(__mut_);
Howard Hinnantccdd2032010-08-30 18:46:21 +0000135 __sub_wait(__lk);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000136 if (__exception_ != nullptr)
137 rethrow_exception(__exception_);
138}
139
140void
Howard Hinnantccdd2032010-08-30 18:46:21 +0000141__assoc_sub_state::wait()
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000142{
143 unique_lock<mutex> __lk(__mut_);
Howard Hinnantccdd2032010-08-30 18:46:21 +0000144 __sub_wait(__lk);
145}
146
147void
148__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
149{
150 if (!__is_ready())
151 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000152 if (__state_ & static_cast<unsigned>(deferred))
Howard Hinnantccdd2032010-08-30 18:46:21 +0000153 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000154 __state_ &= ~static_cast<unsigned>(deferred);
Howard Hinnantccdd2032010-08-30 18:46:21 +0000155 __lk.unlock();
156 __execute();
157 }
158 else
159 while (!__is_ready())
160 __cv_.wait(__lk);
161 }
162}
163
164void
165__assoc_sub_state::__execute()
166{
Marshall Clow9ea94bc2018-07-30 23:33:48 +0000167 __throw_future_error(future_errc::no_state);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000168}
169
170future<void>::future(__assoc_sub_state* __state)
171 : __state_(__state)
172{
Louis Dionne2c0d2262018-08-24 14:00:59 +0000173 __state_->__attach_future();
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000174}
175
176future<void>::~future()
177{
178 if (__state_)
179 __state_->__release_shared();
180}
181
182void
183future<void>::get()
184{
Howard Hinnantccdd2032010-08-30 18:46:21 +0000185 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000186 __assoc_sub_state* __s = __state_;
187 __state_ = nullptr;
Howard Hinnantccdd2032010-08-30 18:46:21 +0000188 __s->copy();
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000189}
190
191promise<void>::promise()
192 : __state_(new __assoc_sub_state)
193{
194}
195
196promise<void>::~promise()
197{
198 if (__state_)
199 {
Asiri Rathnayakeeee23352015-11-10 11:41:22 +0000200#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000201 if (!__state_->__has_value() && __state_->use_count() > 1)
202 __state_->set_exception(make_exception_ptr(
203 future_error(make_error_code(future_errc::broken_promise))
204 ));
Asiri Rathnayakeeee23352015-11-10 11:41:22 +0000205#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000206 __state_->__release_shared();
207 }
208}
209
210future<void>
211promise<void>::get_future()
212{
213 if (__state_ == nullptr)
Marshall Clow9ea94bc2018-07-30 23:33:48 +0000214 __throw_future_error(future_errc::no_state);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000215 return future<void>(__state_);
216}
217
218void
219promise<void>::set_value()
220{
221 if (__state_ == nullptr)
Marshall Clow9ea94bc2018-07-30 23:33:48 +0000222 __throw_future_error(future_errc::no_state);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000223 __state_->set_value();
224}
225
226void
227promise<void>::set_exception(exception_ptr __p)
228{
229 if (__state_ == nullptr)
Marshall Clow9ea94bc2018-07-30 23:33:48 +0000230 __throw_future_error(future_errc::no_state);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000231 __state_->set_exception(__p);
232}
233
234void
235promise<void>::set_value_at_thread_exit()
236{
237 if (__state_ == nullptr)
Marshall Clow9ea94bc2018-07-30 23:33:48 +0000238 __throw_future_error(future_errc::no_state);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000239 __state_->set_value_at_thread_exit();
240}
241
242void
243promise<void>::set_exception_at_thread_exit(exception_ptr __p)
244{
245 if (__state_ == nullptr)
Marshall Clow9ea94bc2018-07-30 23:33:48 +0000246 __throw_future_error(future_errc::no_state);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000247 __state_->set_exception_at_thread_exit(__p);
248}
249
Howard Hinnant92646c42010-09-03 18:39:25 +0000250shared_future<void>::~shared_future()
251{
252 if (__state_)
253 __state_->__release_shared();
254}
255
256shared_future<void>&
257shared_future<void>::operator=(const shared_future& __rhs)
258{
259 if (__rhs.__state_)
260 __rhs.__state_->__add_shared();
261 if (__state_)
262 __state_->__release_shared();
263 __state_ = __rhs.__state_;
264 return *this;
265}
266
Howard Hinnant96803d92010-08-25 17:32:05 +0000267_LIBCPP_END_NAMESPACE_STD
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000268
269#endif // !_LIBCPP_HAS_NO_THREADS