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 18class _LIBCPP_HIDDEN __future_error_category 19 : public __do_message 20{ 21public: 22 virtual const char* name() const _NOEXCEPT; 23 virtual string message(int ev) const; 24}; 25 26const 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 40string 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 67const error_category& 68future_category() _NOEXCEPT 69{ 70 static __future_error_category __f; 71 return __f; 72} 73 74future_error::future_error(error_code __ec) 75 : logic_error(__ec.message()), 76 __ec_(__ec) 77{ 78} 79 80future_error::~future_error() _NOEXCEPT 81{ 82} 83 84void 85__assoc_sub_state::__on_zero_shared() _NOEXCEPT 86{ 87 delete this; 88} 89 90void 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 100void 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 110void 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 121void 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 131void 132__assoc_sub_state::__make_ready() 133{ 134 unique_lock<mutex> __lk(__mut_); 135 __state_ |= ready; 136 __cv_.notify_all(); 137} 138 139void 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 148void 149__assoc_sub_state::wait() 150{ 151 unique_lock<mutex> __lk(__mut_); 152 __sub_wait(__lk); 153} 154 155void 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 172void 173__assoc_sub_state::__execute() 174{ 175 __throw_future_error(future_errc::no_state); 176} 177 178future<void>::future(__assoc_sub_state* __state) 179 : __state_(__state) 180{ 181 __state_->__attach_future(); 182} 183 184future<void>::~future() 185{ 186 if (__state_) 187 __state_->__release_shared(); 188} 189 190void 191future<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 199promise<void>::promise() 200 : __state_(new __assoc_sub_state) 201{ 202} 203 204promise<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 218future<void> 219promise<void>::get_future() 220{ 221 if (__state_ == nullptr) 222 __throw_future_error(future_errc::no_state); 223 return future<void>(__state_); 224} 225 226void 227promise<void>::set_value() 228{ 229 if (__state_ == nullptr) 230 __throw_future_error(future_errc::no_state); 231 __state_->set_value(); 232} 233 234void 235promise<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 242void 243promise<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 250void 251promise<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 258shared_future<void>::~shared_future() 259{ 260 if (__state_) 261 __state_->__release_shared(); 262} 263 264shared_future<void>& 265shared_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