1 //===----------------------------------------------------------------------===//
3 // 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
7 //===----------------------------------------------------------------------===//
12 _LIBCPP_BEGIN_NAMESPACE_STD
14 class _LIBCPP_HIDDEN __future_error_category
: public __do_message
{
16 virtual const char* name() const noexcept
;
17 virtual string
message(int ev
) const;
20 const char* __future_error_category::name() const noexcept
{ return "future"; }
22 _LIBCPP_DIAGNOSTIC_PUSH
23 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")
24 _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")
26 string
__future_error_category::message(int ev
) const {
27 switch (static_cast<future_errc
>(ev
)) {
28 case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)
29 case future_errc::broken_promise
:
30 return string("The associated promise has been destructed prior "
31 "to the associated state becoming ready.");
32 case future_errc::future_already_retrieved
:
33 return string("The future has already been retrieved from "
34 "the promise or packaged_task.");
35 case future_errc::promise_already_satisfied
:
36 return string("The state of the promise has already been set.");
37 case future_errc::no_state
:
38 return string("Operation not permitted on an object without "
39 "an associated state.");
41 return string("unspecified future_errc value\n");
44 _LIBCPP_DIAGNOSTIC_POP
46 const error_category
& future_category() noexcept
{
47 union AvoidDestroyingFutureCategory
{
48 __future_error_category future_error_category
;
49 constexpr explicit AvoidDestroyingFutureCategory() : future_error_category() {}
50 ~AvoidDestroyingFutureCategory() {}
52 constinit
static AvoidDestroyingFutureCategory helper
;
53 return helper
.future_error_category
;
56 future_error::future_error(error_code __ec
) : logic_error(__ec
.message()), __ec_(__ec
) {}
58 future_error::~future_error() noexcept
{}
60 void __assoc_sub_state::__on_zero_shared() noexcept
{ delete this; }
62 void __assoc_sub_state::set_value() {
63 unique_lock
<mutex
> __lk(__mut_
);
65 __throw_future_error(future_errc::promise_already_satisfied
);
66 __state_
|= __constructed
| ready
;
70 void __assoc_sub_state::set_value_at_thread_exit() {
71 unique_lock
<mutex
> __lk(__mut_
);
73 __throw_future_error(future_errc::promise_already_satisfied
);
74 __state_
|= __constructed
;
75 __thread_local_data()->__make_ready_at_thread_exit(this);
78 void __assoc_sub_state::set_exception(exception_ptr __p
) {
79 unique_lock
<mutex
> __lk(__mut_
);
81 __throw_future_error(future_errc::promise_already_satisfied
);
87 void __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p
) {
88 unique_lock
<mutex
> __lk(__mut_
);
90 __throw_future_error(future_errc::promise_already_satisfied
);
92 __thread_local_data()->__make_ready_at_thread_exit(this);
95 void __assoc_sub_state::__make_ready() {
96 unique_lock
<mutex
> __lk(__mut_
);
101 void __assoc_sub_state::copy() {
102 unique_lock
<mutex
> __lk(__mut_
);
104 if (__exception_
!= nullptr)
105 rethrow_exception(__exception_
);
108 void __assoc_sub_state::wait() {
109 unique_lock
<mutex
> __lk(__mut_
);
113 void __assoc_sub_state::__sub_wait(unique_lock
<mutex
>& __lk
) {
115 if (__state_
& static_cast<unsigned>(deferred
)) {
116 __state_
&= ~static_cast<unsigned>(deferred
);
120 while (!__is_ready())
125 void __assoc_sub_state::__execute() { __throw_future_error(future_errc::no_state
); }
127 future
<void>::future(__assoc_sub_state
* __state
) : __state_(__state
) { __state_
->__attach_future(); }
129 future
<void>::~future() {
131 __state_
->__release_shared();
134 void future
<void>::get() {
135 unique_ptr
<__shared_count
, __release_shared_count
> __(__state_
);
136 __assoc_sub_state
* __s
= __state_
;
141 promise
<void>::promise() : __state_(new __assoc_sub_state
) {}
143 promise
<void>::~promise() {
145 #if _LIBCPP_HAS_EXCEPTIONS
146 if (!__state_
->__has_value() && __state_
->use_count() > 1)
147 __state_
->set_exception(make_exception_ptr(future_error(future_errc::broken_promise
)));
148 #endif // _LIBCPP_HAS_EXCEPTIONS
149 __state_
->__release_shared();
153 future
<void> promise
<void>::get_future() {
154 if (__state_
== nullptr)
155 __throw_future_error(future_errc::no_state
);
156 return future
<void>(__state_
);
159 void promise
<void>::set_value() {
160 if (__state_
== nullptr)
161 __throw_future_error(future_errc::no_state
);
162 __state_
->set_value();
165 void promise
<void>::set_exception(exception_ptr __p
) {
166 if (__state_
== nullptr)
167 __throw_future_error(future_errc::no_state
);
168 __state_
->set_exception(__p
);
171 void promise
<void>::set_value_at_thread_exit() {
172 if (__state_
== nullptr)
173 __throw_future_error(future_errc::no_state
);
174 __state_
->set_value_at_thread_exit();
177 void promise
<void>::set_exception_at_thread_exit(exception_ptr __p
) {
178 if (__state_
== nullptr)
179 __throw_future_error(future_errc::no_state
);
180 __state_
->set_exception_at_thread_exit(__p
);
183 shared_future
<void>::~shared_future() {
185 __state_
->__release_shared();
188 shared_future
<void>& shared_future
<void>::operator=(const shared_future
& __rhs
) {
190 __rhs
.__state_
->__add_shared();
192 __state_
->__release_shared();
193 __state_
= __rhs
.__state_
;
197 _LIBCPP_END_NAMESPACE_STD