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 if (__has_value()) 96 __throw_future_error(future_errc::promise_already_satisfied); 97 __state_ |= __constructed | ready; 98 __cv_.notify_all(); 99 } 100 101 void set_value_at_thread_exit()102__assoc_sub_state::set_value_at_thread_exit() 103 { 104 unique_lock<mutex> __lk(__mut_); 105 if (__has_value()) 106 __throw_future_error(future_errc::promise_already_satisfied); 107 __state_ |= __constructed; 108 __thread_local_data()->__make_ready_at_thread_exit(this); 109 } 110 111 void set_exception(exception_ptr __p)112__assoc_sub_state::set_exception(exception_ptr __p) 113 { 114 unique_lock<mutex> __lk(__mut_); 115 if (__has_value()) 116 __throw_future_error(future_errc::promise_already_satisfied); 117 __exception_ = __p; 118 __state_ |= ready; 119 __cv_.notify_all(); 120 } 121 122 void set_exception_at_thread_exit(exception_ptr __p)123__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) 124 { 125 unique_lock<mutex> __lk(__mut_); 126 if (__has_value()) 127 __throw_future_error(future_errc::promise_already_satisfied); 128 __exception_ = __p; 129 __thread_local_data()->__make_ready_at_thread_exit(this); 130 } 131 132 void __make_ready()133__assoc_sub_state::__make_ready() 134 { 135 unique_lock<mutex> __lk(__mut_); 136 __state_ |= ready; 137 __cv_.notify_all(); 138 } 139 140 void copy()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 wait()150__assoc_sub_state::wait() 151 { 152 unique_lock<mutex> __lk(__mut_); 153 __sub_wait(__lk); 154 } 155 156 void __sub_wait(unique_lock<mutex> & __lk)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 __execute()174__assoc_sub_state::__execute() 175 { 176 __throw_future_error(future_errc::no_state); 177 } 178 future(__assoc_sub_state * __state)179future<void>::future(__assoc_sub_state* __state) 180 : __state_(__state) 181 { 182 __state_->__attach_future(); 183 } 184 ~future()185future<void>::~future() 186 { 187 if (__state_) 188 __state_->__release_shared(); 189 } 190 191 void get()192future<void>::get() 193 { 194 unique_ptr<__shared_count, __release_shared_count> __(__state_); 195 __assoc_sub_state* __s = __state_; 196 __state_ = nullptr; 197 __s->copy(); 198 } 199 promise()200promise<void>::promise() 201 : __state_(new __assoc_sub_state) 202 { 203 } 204 ~promise()205promise<void>::~promise() 206 { 207 if (__state_) 208 { 209 #ifndef _LIBCPP_NO_EXCEPTIONS 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 #endif // _LIBCPP_NO_EXCEPTIONS 215 __state_->__release_shared(); 216 } 217 } 218 219 future<void> get_future()220promise<void>::get_future() 221 { 222 if (__state_ == nullptr) 223 __throw_future_error(future_errc::no_state); 224 return future<void>(__state_); 225 } 226 227 void set_value()228promise<void>::set_value() 229 { 230 if (__state_ == nullptr) 231 __throw_future_error(future_errc::no_state); 232 __state_->set_value(); 233 } 234 235 void set_exception(exception_ptr __p)236promise<void>::set_exception(exception_ptr __p) 237 { 238 if (__state_ == nullptr) 239 __throw_future_error(future_errc::no_state); 240 __state_->set_exception(__p); 241 } 242 243 void set_value_at_thread_exit()244promise<void>::set_value_at_thread_exit() 245 { 246 if (__state_ == nullptr) 247 __throw_future_error(future_errc::no_state); 248 __state_->set_value_at_thread_exit(); 249 } 250 251 void set_exception_at_thread_exit(exception_ptr __p)252promise<void>::set_exception_at_thread_exit(exception_ptr __p) 253 { 254 if (__state_ == nullptr) 255 __throw_future_error(future_errc::no_state); 256 __state_->set_exception_at_thread_exit(__p); 257 } 258 ~shared_future()259shared_future<void>::~shared_future() 260 { 261 if (__state_) 262 __state_->__release_shared(); 263 } 264 265 shared_future<void>& operator =(const shared_future & __rhs)266shared_future<void>::operator=(const shared_future& __rhs) 267 { 268 if (__rhs.__state_) 269 __rhs.__state_->__add_shared(); 270 if (__state_) 271 __state_->__release_shared(); 272 __state_ = __rhs.__state_; 273 return *this; 274 } 275 276 _LIBCPP_END_NAMESPACE_STD 277 278 #endif // !_LIBCPP_HAS_NO_THREADS 279