1 //===------------------------- future.cpp ---------------------------------===// 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 "__config" 10 11 #ifndef _LIBCPP_HAS_NO_THREADS 12 13 #include "future" 14 #include "string" 15 16 _LIBCPP_BEGIN_NAMESPACE_STD 17 18 class _LIBCPP_HIDDEN __future_error_category 19 : public __do_message 20 { 21 public: 22 virtual const char* name() const noexcept; 23 virtual string message(int ev) const; 24 }; 25 26 const char* 27 __future_error_category::name() const noexcept 28 { 29 return "future"; 30 } 31 32 #if defined(__clang__) 33 #pragma clang diagnostic push 34 #pragma clang diagnostic ignored "-Wswitch" 35 #elif defined(__GNUC__) || defined(__GNUG__) 36 #pragma GCC diagnostic push 37 #pragma GCC diagnostic ignored "-Wswitch" 38 #endif 39 40 string 41 __future_error_category::message(int ev) const 42 { 43 switch (static_cast<future_errc>(ev)) 44 { 45 case future_errc(0): // For backwards compatibility with C++11 (LWG 2056) 46 case future_errc::broken_promise: 47 return string("The associated promise has been destructed prior " 48 "to the associated state becoming ready."); 49 case future_errc::future_already_retrieved: 50 return string("The future has already been retrieved from " 51 "the promise or packaged_task."); 52 case future_errc::promise_already_satisfied: 53 return string("The state of the promise has already been set."); 54 case future_errc::no_state: 55 return string("Operation not permitted on an object without " 56 "an associated state."); 57 } 58 return string("unspecified future_errc value\n"); 59 } 60 61 #if defined(__clang__) 62 #pragma clang diagnostic pop 63 #elif defined(__GNUC__) || defined(__GNUG__) 64 #pragma GCC diagnostic pop 65 #endif 66 67 const error_category& 68 future_category() noexcept 69 { 70 static __future_error_category __f; 71 return __f; 72 } 73 74 future_error::future_error(error_code __ec) 75 : logic_error(__ec.message()), 76 __ec_(__ec) 77 { 78 } 79 80 future_error::~future_error() noexcept 81 { 82 } 83 84 void 85 __assoc_sub_state::__on_zero_shared() noexcept 86 { 87 delete this; 88 } 89 90 void 91 __assoc_sub_state::set_value() 92 { 93 unique_lock<mutex> __lk(__mut_); 94 if (__has_value()) 95 __throw_future_error(future_errc::promise_already_satisfied); 96 __state_ |= __constructed | ready; 97 __cv_.notify_all(); 98 } 99 100 void 101 __assoc_sub_state::set_value_at_thread_exit() 102 { 103 unique_lock<mutex> __lk(__mut_); 104 if (__has_value()) 105 __throw_future_error(future_errc::promise_already_satisfied); 106 __state_ |= __constructed; 107 __thread_local_data()->__make_ready_at_thread_exit(this); 108 } 109 110 void 111 __assoc_sub_state::set_exception(exception_ptr __p) 112 { 113 unique_lock<mutex> __lk(__mut_); 114 if (__has_value()) 115 __throw_future_error(future_errc::promise_already_satisfied); 116 __exception_ = __p; 117 __state_ |= ready; 118 __cv_.notify_all(); 119 } 120 121 void 122 __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) 123 { 124 unique_lock<mutex> __lk(__mut_); 125 if (__has_value()) 126 __throw_future_error(future_errc::promise_already_satisfied); 127 __exception_ = __p; 128 __thread_local_data()->__make_ready_at_thread_exit(this); 129 } 130 131 void 132 __assoc_sub_state::__make_ready() 133 { 134 unique_lock<mutex> __lk(__mut_); 135 __state_ |= ready; 136 __cv_.notify_all(); 137 } 138 139 void 140 __assoc_sub_state::copy() 141 { 142 unique_lock<mutex> __lk(__mut_); 143 __sub_wait(__lk); 144 if (__exception_ != nullptr) 145 rethrow_exception(__exception_); 146 } 147 148 void 149 __assoc_sub_state::wait() 150 { 151 unique_lock<mutex> __lk(__mut_); 152 __sub_wait(__lk); 153 } 154 155 void 156 __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) 157 { 158 if (!__is_ready()) 159 { 160 if (__state_ & static_cast<unsigned>(deferred)) 161 { 162 __state_ &= ~static_cast<unsigned>(deferred); 163 __lk.unlock(); 164 __execute(); 165 } 166 else 167 while (!__is_ready()) 168 __cv_.wait(__lk); 169 } 170 } 171 172 void 173 __assoc_sub_state::__execute() 174 { 175 __throw_future_error(future_errc::no_state); 176 } 177 178 future<void>::future(__assoc_sub_state* __state) 179 : __state_(__state) 180 { 181 __state_->__attach_future(); 182 } 183 184 future<void>::~future() 185 { 186 if (__state_) 187 __state_->__release_shared(); 188 } 189 190 void 191 future<void>::get() 192 { 193 unique_ptr<__shared_count, __release_shared_count> __(__state_); 194 __assoc_sub_state* __s = __state_; 195 __state_ = nullptr; 196 __s->copy(); 197 } 198 199 promise<void>::promise() 200 : __state_(new __assoc_sub_state) 201 { 202 } 203 204 promise<void>::~promise() 205 { 206 if (__state_) 207 { 208 #ifndef _LIBCPP_NO_EXCEPTIONS 209 if (!__state_->__has_value() && __state_->use_count() > 1) 210 __state_->set_exception(make_exception_ptr( 211 future_error(make_error_code(future_errc::broken_promise)) 212 )); 213 #endif // _LIBCPP_NO_EXCEPTIONS 214 __state_->__release_shared(); 215 } 216 } 217 218 future<void> 219 promise<void>::get_future() 220 { 221 if (__state_ == nullptr) 222 __throw_future_error(future_errc::no_state); 223 return future<void>(__state_); 224 } 225 226 void 227 promise<void>::set_value() 228 { 229 if (__state_ == nullptr) 230 __throw_future_error(future_errc::no_state); 231 __state_->set_value(); 232 } 233 234 void 235 promise<void>::set_exception(exception_ptr __p) 236 { 237 if (__state_ == nullptr) 238 __throw_future_error(future_errc::no_state); 239 __state_->set_exception(__p); 240 } 241 242 void 243 promise<void>::set_value_at_thread_exit() 244 { 245 if (__state_ == nullptr) 246 __throw_future_error(future_errc::no_state); 247 __state_->set_value_at_thread_exit(); 248 } 249 250 void 251 promise<void>::set_exception_at_thread_exit(exception_ptr __p) 252 { 253 if (__state_ == nullptr) 254 __throw_future_error(future_errc::no_state); 255 __state_->set_exception_at_thread_exit(__p); 256 } 257 258 shared_future<void>::~shared_future() 259 { 260 if (__state_) 261 __state_->__release_shared(); 262 } 263 264 shared_future<void>& 265 shared_future<void>::operator=(const shared_future& __rhs) 266 { 267 if (__rhs.__state_) 268 __rhs.__state_->__add_shared(); 269 if (__state_) 270 __state_->__release_shared(); 271 __state_ = __rhs.__state_; 272 return *this; 273 } 274 275 _LIBCPP_END_NAMESPACE_STD 276 277 #endif // !_LIBCPP_HAS_NO_THREADS 278