1 //===----------------------------------------------------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <future> 10 #include <string> 11 12 _LIBCPP_BEGIN_NAMESPACE_STD 13 14 class _LIBCPP_HIDDEN __future_error_category : public __do_message { 15 public: 16 virtual const char* name() const noexcept; 17 virtual string message(int ev) const; 18 }; 19 20 const char* __future_error_category::name() const noexcept { return "future"; } 21 22 _LIBCPP_DIAGNOSTIC_PUSH 23 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch") 24 _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch") 25 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."); 40 } 41 return string("unspecified future_errc value\n"); 42 } 43 44 _LIBCPP_DIAGNOSTIC_POP 45 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() {} 51 }; 52 constinit static AvoidDestroyingFutureCategory helper; 53 return helper.future_error_category; 54 } 55 56 future_error::future_error(error_code __ec) : logic_error(__ec.message()), __ec_(__ec) {} 57 58 future_error::~future_error() noexcept {} 59 60 void __assoc_sub_state::__on_zero_shared() noexcept { delete this; } 61 62 void __assoc_sub_state::set_value() { 63 unique_lock<mutex> __lk(__mut_); 64 if (__has_value()) 65 __throw_future_error(future_errc::promise_already_satisfied); 66 __state_ |= __constructed | ready; 67 __cv_.notify_all(); 68 } 69 70 void __assoc_sub_state::set_value_at_thread_exit() { 71 unique_lock<mutex> __lk(__mut_); 72 if (__has_value()) 73 __throw_future_error(future_errc::promise_already_satisfied); 74 __state_ |= __constructed; 75 __thread_local_data()->__make_ready_at_thread_exit(this); 76 } 77 78 void __assoc_sub_state::set_exception(exception_ptr __p) { 79 unique_lock<mutex> __lk(__mut_); 80 if (__has_value()) 81 __throw_future_error(future_errc::promise_already_satisfied); 82 __exception_ = __p; 83 __state_ |= ready; 84 __cv_.notify_all(); 85 } 86 87 void __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) { 88 unique_lock<mutex> __lk(__mut_); 89 if (__has_value()) 90 __throw_future_error(future_errc::promise_already_satisfied); 91 __exception_ = __p; 92 __thread_local_data()->__make_ready_at_thread_exit(this); 93 } 94 95 void __assoc_sub_state::__make_ready() { 96 unique_lock<mutex> __lk(__mut_); 97 __state_ |= ready; 98 __cv_.notify_all(); 99 } 100 101 void __assoc_sub_state::copy() { 102 unique_lock<mutex> __lk(__mut_); 103 __sub_wait(__lk); 104 if (__exception_ != nullptr) 105 rethrow_exception(__exception_); 106 } 107 108 void __assoc_sub_state::wait() { 109 unique_lock<mutex> __lk(__mut_); 110 __sub_wait(__lk); 111 } 112 113 void __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) { 114 if (!__is_ready()) { 115 if (__state_ & static_cast<unsigned>(deferred)) { 116 __state_ &= ~static_cast<unsigned>(deferred); 117 __lk.unlock(); 118 __execute(); 119 } else 120 while (!__is_ready()) 121 __cv_.wait(__lk); 122 } 123 } 124 125 void __assoc_sub_state::__execute() { __throw_future_error(future_errc::no_state); } 126 127 future<void>::future(__assoc_sub_state* __state) : __state_(__state) { __state_->__attach_future(); } 128 129 future<void>::~future() { 130 if (__state_) 131 __state_->__release_shared(); 132 } 133 134 void future<void>::get() { 135 unique_ptr<__shared_count, __release_shared_count> __(__state_); 136 __assoc_sub_state* __s = __state_; 137 __state_ = nullptr; 138 __s->copy(); 139 } 140 141 promise<void>::promise() : __state_(new __assoc_sub_state) {} 142 143 promise<void>::~promise() { 144 if (__state_) { 145 #ifndef _LIBCPP_HAS_NO_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_NO_EXCEPTIONS 149 __state_->__release_shared(); 150 } 151 } 152 153 future<void> promise<void>::get_future() { 154 if (__state_ == nullptr) 155 __throw_future_error(future_errc::no_state); 156 return future<void>(__state_); 157 } 158 159 void promise<void>::set_value() { 160 if (__state_ == nullptr) 161 __throw_future_error(future_errc::no_state); 162 __state_->set_value(); 163 } 164 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); 169 } 170 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(); 175 } 176 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); 181 } 182 183 shared_future<void>::~shared_future() { 184 if (__state_) 185 __state_->__release_shared(); 186 } 187 188 shared_future<void>& shared_future<void>::operator=(const shared_future& __rhs) { 189 if (__rhs.__state_) 190 __rhs.__state_->__add_shared(); 191 if (__state_) 192 __state_->__release_shared(); 193 __state_ = __rhs.__state_; 194 return *this; 195 } 196 197 _LIBCPP_END_NAMESPACE_STD 198