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