blob: 07ae9389ec238c4d737f0c67c66ab5e95e9c8da6 [file] [log] [blame]
Louis Dionneeb8650a2021-11-17 21:25:011//===----------------------------------------------------------------------===//
Howard Hinnantdae34812010-08-25 17:32:052//
Chandler Carruth57b08b02019-01-19 10:56:403// 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 Hinnantdae34812010-08-25 17:32:056//
7//===----------------------------------------------------------------------===//
8
Jonathan Roelofsb3fcc672014-09-05 19:45:059#include "__config"
10
11#ifndef _LIBCPP_HAS_NO_THREADS
12
Howard Hinnantdae34812010-08-25 17:32:0513#include "future"
14#include "string"
15
16_LIBCPP_BEGIN_NAMESPACE_STD
17
18class _LIBCPP_HIDDEN __future_error_category
19 : public __do_message
20{
21public:
Louis Dionne56013052021-03-01 17:09:4522 virtual const char* name() const noexcept;
Howard Hinnantdae34812010-08-25 17:32:0523 virtual string message(int ev) const;
24};
25
26const char*
Louis Dionne56013052021-03-01 17:09:4527__future_error_category::name() const noexcept
Howard Hinnantdae34812010-08-25 17:32:0528{
29 return "future";
30}
31
Nikolas Klausera7c2a622022-02-14 17:52:2832_LIBCPP_DIAGNOSTIC_PUSH
33_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")
34_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")
Howard Hinnant3b2d7ee2013-09-14 18:20:1035
Howard Hinnantdae34812010-08-25 17:32:0536string
37__future_error_category::message(int ev) const
38{
Howard Hinnantbe745c82012-02-02 20:31:3639 switch (static_cast<future_errc>(ev))
Howard Hinnantdae34812010-08-25 17:32:0540 {
Howard Hinnant3b2d7ee2013-09-14 18:20:1041 case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)
Howard Hinnantdae34812010-08-25 17:32:0542 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 Klausera7c2a622022-02-14 17:52:2857_LIBCPP_DIAGNOSTIC_POP
Howard Hinnant3b2d7ee2013-09-14 18:20:1058
Howard Hinnantdae34812010-08-25 17:32:0559const error_category&
Louis Dionne56013052021-03-01 17:09:4560future_category() noexcept
Howard Hinnantdae34812010-08-25 17:32:0561{
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 Dionne56013052021-03-01 17:09:4572future_error::~future_error() noexcept
Howard Hinnant3aa229f2011-07-08 00:04:4073{
74}
75
Howard Hinnant167fd102010-08-27 20:10:1976void
Louis Dionne56013052021-03-01 17:09:4577__assoc_sub_state::__on_zero_shared() noexcept
Howard Hinnant167fd102010-08-27 20:10:1978{
79 delete this;
80}
81
82void
83__assoc_sub_state::set_value()
84{
85 unique_lock<mutex> __lk(__mut_);
86 if (__has_value())
Marshall Clow934864b2018-07-30 23:33:4887 __throw_future_error(future_errc::promise_already_satisfied);
Howard Hinnant167fd102010-08-27 20:10:1988 __state_ |= __constructed | ready;
Howard Hinnant167fd102010-08-27 20:10:1989 __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 Clow934864b2018-07-30 23:33:4897 __throw_future_error(future_errc::promise_already_satisfied);
Howard Hinnant167fd102010-08-27 20:10:1998 __state_ |= __constructed;
Howard Hinnant10e4a482010-10-14 19:18:0499 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant167fd102010-08-27 20:10:19100}
101
102void
103__assoc_sub_state::set_exception(exception_ptr __p)
104{
105 unique_lock<mutex> __lk(__mut_);
106 if (__has_value())
Marshall Clow934864b2018-07-30 23:33:48107 __throw_future_error(future_errc::promise_already_satisfied);
Howard Hinnant167fd102010-08-27 20:10:19108 __exception_ = __p;
109 __state_ |= ready;
Howard Hinnant167fd102010-08-27 20:10:19110 __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 Clow934864b2018-07-30 23:33:48118 __throw_future_error(future_errc::promise_already_satisfied);
Howard Hinnant167fd102010-08-27 20:10:19119 __exception_ = __p;
Howard Hinnant10e4a482010-10-14 19:18:04120 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant167fd102010-08-27 20:10:19121}
122
123void
124__assoc_sub_state::__make_ready()
125{
126 unique_lock<mutex> __lk(__mut_);
127 __state_ |= ready;
Howard Hinnant167fd102010-08-27 20:10:19128 __cv_.notify_all();
129}
130
131void
132__assoc_sub_state::copy()
133{
134 unique_lock<mutex> __lk(__mut_);
Howard Hinnant27f000e2010-08-30 18:46:21135 __sub_wait(__lk);
Howard Hinnant167fd102010-08-27 20:10:19136 if (__exception_ != nullptr)
137 rethrow_exception(__exception_);
138}
139
140void
Howard Hinnant27f000e2010-08-30 18:46:21141__assoc_sub_state::wait()
Howard Hinnant167fd102010-08-27 20:10:19142{
143 unique_lock<mutex> __lk(__mut_);
Howard Hinnant27f000e2010-08-30 18:46:21144 __sub_wait(__lk);
145}
146
147void
148__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
149{
150 if (!__is_ready())
151 {
Howard Hinnantc2063662011-12-01 20:21:04152 if (__state_ & static_cast<unsigned>(deferred))
Howard Hinnant27f000e2010-08-30 18:46:21153 {
Howard Hinnantc2063662011-12-01 20:21:04154 __state_ &= ~static_cast<unsigned>(deferred);
Howard Hinnant27f000e2010-08-30 18:46:21155 __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 Clow934864b2018-07-30 23:33:48167 __throw_future_error(future_errc::no_state);
Howard Hinnant167fd102010-08-27 20:10:19168}
169
170future<void>::future(__assoc_sub_state* __state)
171 : __state_(__state)
172{
Louis Dionne616ef182018-08-24 14:00:59173 __state_->__attach_future();
Howard Hinnant167fd102010-08-27 20:10:19174}
175
176future<void>::~future()
177{
178 if (__state_)
179 __state_->__release_shared();
180}
181
182void
183future<void>::get()
184{
Howard Hinnant27f000e2010-08-30 18:46:21185 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant167fd102010-08-27 20:10:19186 __assoc_sub_state* __s = __state_;
187 __state_ = nullptr;
Howard Hinnant27f000e2010-08-30 18:46:21188 __s->copy();
Howard Hinnant167fd102010-08-27 20:10:19189}
190
191promise<void>::promise()
192 : __state_(new __assoc_sub_state)
193{
194}
195
196promise<void>::~promise()
197{
198 if (__state_)
199 {
Asiri Rathnayakef520c142015-11-10 11:41:22200#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant167fd102010-08-27 20:10:19201 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 Rathnayakef520c142015-11-10 11:41:22205#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant167fd102010-08-27 20:10:19206 __state_->__release_shared();
207 }
208}
209
210future<void>
211promise<void>::get_future()
212{
213 if (__state_ == nullptr)
Marshall Clow934864b2018-07-30 23:33:48214 __throw_future_error(future_errc::no_state);
Howard Hinnant167fd102010-08-27 20:10:19215 return future<void>(__state_);
216}
217
218void
219promise<void>::set_value()
220{
221 if (__state_ == nullptr)
Marshall Clow934864b2018-07-30 23:33:48222 __throw_future_error(future_errc::no_state);
Howard Hinnant167fd102010-08-27 20:10:19223 __state_->set_value();
224}
225
226void
227promise<void>::set_exception(exception_ptr __p)
228{
229 if (__state_ == nullptr)
Marshall Clow934864b2018-07-30 23:33:48230 __throw_future_error(future_errc::no_state);
Howard Hinnant167fd102010-08-27 20:10:19231 __state_->set_exception(__p);
232}
233
234void
235promise<void>::set_value_at_thread_exit()
236{
237 if (__state_ == nullptr)
Marshall Clow934864b2018-07-30 23:33:48238 __throw_future_error(future_errc::no_state);
Howard Hinnant167fd102010-08-27 20:10:19239 __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 Clow934864b2018-07-30 23:33:48246 __throw_future_error(future_errc::no_state);
Howard Hinnant167fd102010-08-27 20:10:19247 __state_->set_exception_at_thread_exit(__p);
248}
249
Howard Hinnantead85502010-09-03 18:39:25250shared_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 Hinnantdae34812010-08-25 17:32:05267_LIBCPP_END_NAMESPACE_STD
Jonathan Roelofsb3fcc672014-09-05 19:45:05268
269#endif // !_LIBCPP_HAS_NO_THREADS