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