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