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 15 class _LIBCPP_HIDDEN __future_error_category 16 : public __do_message 17 { 18 public: 19 virtual const char* name() const _NOEXCEPT; 20 virtual string message(int ev) const; 21 }; 22 23 const char* name() const24__future_error_category::name() const _NOEXCEPT 25 { 26 return "future"; 27 } 28 29 string message(int ev) const30__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 49 const error_category& future_category()50future_category() _NOEXCEPT 51 { 52 static __future_error_category __f; 53 return __f; 54 } 55 future_error(error_code __ec)56future_error::future_error(error_code __ec) 57 : logic_error(__ec.message()), 58 __ec_(__ec) 59 { 60 } 61 ~future_error()62future_error::~future_error() _NOEXCEPT 63 { 64 } 65 66 void __on_zero_shared()67__assoc_sub_state::__on_zero_shared() _NOEXCEPT 68 { 69 delete this; 70 } 71 72 void set_value()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 85 void set_value_at_thread_exit()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 98 void set_exception(exception_ptr __p)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 112 void set_exception_at_thread_exit(exception_ptr __p)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 125 void __make_ready()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 134 void copy()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 143 void wait()144__assoc_sub_state::wait() 145 { 146 unique_lock<mutex> __lk(__mut_); 147 __sub_wait(__lk); 148 } 149 150 void __sub_wait(unique_lock<mutex> & __lk)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 167 void __execute()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 future(__assoc_sub_state * __state)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 ~future()186future<void>::~future() 187 { 188 if (__state_) 189 __state_->__release_shared(); 190 } 191 192 void get()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 promise()201promise<void>::promise() 202 : __state_(new __assoc_sub_state) 203 { 204 } 205 ~promise()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 218 future<void> get_future()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 228 void set_value()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 238 void set_exception(exception_ptr __p)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 248 void set_value_at_thread_exit()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 258 void set_exception_at_thread_exit(exception_ptr __p)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 ~shared_future()268shared_future<void>::~shared_future() 269 { 270 if (__state_) 271 __state_->__release_shared(); 272 } 273 274 shared_future<void>& operator =(const shared_future & __rhs)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