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