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 19 class _LIBCPP_HIDDEN __future_error_category 20 : public __do_message 21 { 22 public: 23 virtual const char* name() const _NOEXCEPT; 24 virtual string message(int ev) const; 25 }; 26 27 const char* name() const28__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 41 string message(int ev) const42__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 68 const error_category& future_category()69future_category() _NOEXCEPT 70 { 71 static __future_error_category __f; 72 return __f; 73 } 74 future_error(error_code __ec)75future_error::future_error(error_code __ec) 76 : logic_error(__ec.message()), 77 __ec_(__ec) 78 { 79 } 80 ~future_error()81future_error::~future_error() _NOEXCEPT 82 { 83 } 84 85 void __on_zero_shared()86__assoc_sub_state::__on_zero_shared() _NOEXCEPT 87 { 88 delete this; 89 } 90 91 void set_value()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 104 void set_value_at_thread_exit()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 117 void set_exception(exception_ptr __p)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 131 void set_exception_at_thread_exit(exception_ptr __p)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 144 void __make_ready()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 153 void copy()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 162 void wait()163__assoc_sub_state::wait() 164 { 165 unique_lock<mutex> __lk(__mut_); 166 __sub_wait(__lk); 167 } 168 169 void __sub_wait(unique_lock<mutex> & __lk)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 186 void __execute()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 future(__assoc_sub_state * __state)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 ~future()205future<void>::~future() 206 { 207 if (__state_) 208 __state_->__release_shared(); 209 } 210 211 void get()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 promise()220promise<void>::promise() 221 : __state_(new __assoc_sub_state) 222 { 223 } 224 ~promise()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 237 future<void> get_future()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 247 void set_value()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 257 void set_exception(exception_ptr __p)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 267 void set_value_at_thread_exit()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 277 void set_exception_at_thread_exit(exception_ptr __p)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 ~shared_future()287shared_future<void>::~shared_future() 288 { 289 if (__state_) 290 __state_->__release_shared(); 291 } 292 293 shared_future<void>& operator =(const shared_future & __rhs)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