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 __lk.unlock(); 102} 103 104void 105__assoc_sub_state::set_value_at_thread_exit() 106{ 107 unique_lock<mutex> __lk(__mut_); 108#ifndef _LIBCPP_NO_EXCEPTIONS 109 if (__has_value()) 110 throw future_error(make_error_code(future_errc::promise_already_satisfied)); 111#endif 112 __state_ |= __constructed; 113 __thread_local_data()->__make_ready_at_thread_exit(this); 114 __lk.unlock(); 115} 116 117void 118__assoc_sub_state::set_exception(exception_ptr __p) 119{ 120 unique_lock<mutex> __lk(__mut_); 121#ifndef _LIBCPP_NO_EXCEPTIONS 122 if (__has_value()) 123 throw future_error(make_error_code(future_errc::promise_already_satisfied)); 124#endif 125 __exception_ = __p; 126 __state_ |= ready; 127 __lk.unlock(); 128 __cv_.notify_all(); 129} 130 131void 132__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) 133{ 134 unique_lock<mutex> __lk(__mut_); 135#ifndef _LIBCPP_NO_EXCEPTIONS 136 if (__has_value()) 137 throw future_error(make_error_code(future_errc::promise_already_satisfied)); 138#endif 139 __exception_ = __p; 140 __thread_local_data()->__make_ready_at_thread_exit(this); 141 __lk.unlock(); 142} 143 144void 145__assoc_sub_state::__make_ready() 146{ 147 unique_lock<mutex> __lk(__mut_); 148 __state_ |= ready; 149 __lk.unlock(); 150 __cv_.notify_all(); 151} 152 153void 154__assoc_sub_state::copy() 155{ 156 unique_lock<mutex> __lk(__mut_); 157 __sub_wait(__lk); 158 if (__exception_ != nullptr) 159 rethrow_exception(__exception_); 160} 161 162void 163__assoc_sub_state::wait() 164{ 165 unique_lock<mutex> __lk(__mut_); 166 __sub_wait(__lk); 167} 168 169void 170__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) 171{ 172 if (!__is_ready()) 173 { 174 if (__state_ & static_cast<unsigned>(deferred)) 175 { 176 __state_ &= ~static_cast<unsigned>(deferred); 177 __lk.unlock(); 178 __execute(); 179 } 180 else 181 while (!__is_ready()) 182 __cv_.wait(__lk); 183 } 184} 185 186void 187__assoc_sub_state::__execute() 188{ 189#ifndef _LIBCPP_NO_EXCEPTIONS 190 throw future_error(make_error_code(future_errc::no_state)); 191#endif 192} 193 194future<void>::future(__assoc_sub_state* __state) 195 : __state_(__state) 196{ 197#ifndef _LIBCPP_NO_EXCEPTIONS 198 if (__state_->__has_future_attached()) 199 throw future_error(make_error_code(future_errc::future_already_retrieved)); 200#endif 201 __state_->__add_shared(); 202 __state_->__set_future_attached(); 203} 204 205future<void>::~future() 206{ 207 if (__state_) 208 __state_->__release_shared(); 209} 210 211void 212future<void>::get() 213{ 214 unique_ptr<__shared_count, __release_shared_count> __(__state_); 215 __assoc_sub_state* __s = __state_; 216 __state_ = nullptr; 217 __s->copy(); 218} 219 220promise<void>::promise() 221 : __state_(new __assoc_sub_state) 222{ 223} 224 225promise<void>::~promise() 226{ 227 if (__state_) 228 { 229 if (!__state_->__has_value() && __state_->use_count() > 1) 230 __state_->set_exception(make_exception_ptr( 231 future_error(make_error_code(future_errc::broken_promise)) 232 )); 233 __state_->__release_shared(); 234 } 235} 236 237future<void> 238promise<void>::get_future() 239{ 240#ifndef _LIBCPP_NO_EXCEPTIONS 241 if (__state_ == nullptr) 242 throw future_error(make_error_code(future_errc::no_state)); 243#endif 244 return future<void>(__state_); 245} 246 247void 248promise<void>::set_value() 249{ 250#ifndef _LIBCPP_NO_EXCEPTIONS 251 if (__state_ == nullptr) 252 throw future_error(make_error_code(future_errc::no_state)); 253#endif 254 __state_->set_value(); 255} 256 257void 258promise<void>::set_exception(exception_ptr __p) 259{ 260#ifndef _LIBCPP_NO_EXCEPTIONS 261 if (__state_ == nullptr) 262 throw future_error(make_error_code(future_errc::no_state)); 263#endif 264 __state_->set_exception(__p); 265} 266 267void 268promise<void>::set_value_at_thread_exit() 269{ 270#ifndef _LIBCPP_NO_EXCEPTIONS 271 if (__state_ == nullptr) 272 throw future_error(make_error_code(future_errc::no_state)); 273#endif 274 __state_->set_value_at_thread_exit(); 275} 276 277void 278promise<void>::set_exception_at_thread_exit(exception_ptr __p) 279{ 280#ifndef _LIBCPP_NO_EXCEPTIONS 281 if (__state_ == nullptr) 282 throw future_error(make_error_code(future_errc::no_state)); 283#endif 284 __state_->set_exception_at_thread_exit(__p); 285} 286 287shared_future<void>::~shared_future() 288{ 289 if (__state_) 290 __state_->__release_shared(); 291} 292 293shared_future<void>& 294shared_future<void>::operator=(const shared_future& __rhs) 295{ 296 if (__rhs.__state_) 297 __rhs.__state_->__add_shared(); 298 if (__state_) 299 __state_->__release_shared(); 300 __state_ = __rhs.__state_; 301 return *this; 302} 303 304_LIBCPP_END_NAMESPACE_STD 305 306#endif // !_LIBCPP_HAS_NO_THREADS 307