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* 28 __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 42 __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& 69 future_category() _NOEXCEPT 70 { 71 static __future_error_category __f; 72 return __f; 73 } 74 75 future_error::future_error(error_code __ec) 76 : logic_error(__ec.message()), 77 __ec_(__ec) 78 { 79 } 80 81 future_error::~future_error() _NOEXCEPT 82 { 83 } 84 85 void 86 __assoc_sub_state::__on_zero_shared() _NOEXCEPT 87 { 88 delete this; 89 } 90 91 void 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 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 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 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 133 __assoc_sub_state::__make_ready() 134 { 135 unique_lock<mutex> __lk(__mut_); 136 __state_ |= ready; 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 __throw_future_error(future_errc::no_state); 177 } 178 179 future<void>::future(__assoc_sub_state* __state) 180 : __state_(__state) 181 { 182 if (__state_->__has_future_attached()) 183 __throw_future_error(future_errc::future_already_retrieved); 184 __state_->__add_shared(); 185 __state_->__set_future_attached(); 186 } 187 188 future<void>::~future() 189 { 190 if (__state_) 191 __state_->__release_shared(); 192 } 193 194 void 195 future<void>::get() 196 { 197 unique_ptr<__shared_count, __release_shared_count> __(__state_); 198 __assoc_sub_state* __s = __state_; 199 __state_ = nullptr; 200 __s->copy(); 201 } 202 203 promise<void>::promise() 204 : __state_(new __assoc_sub_state) 205 { 206 } 207 208 promise<void>::~promise() 209 { 210 if (__state_) 211 { 212 #ifndef _LIBCPP_NO_EXCEPTIONS 213 if (!__state_->__has_value() && __state_->use_count() > 1) 214 __state_->set_exception(make_exception_ptr( 215 future_error(make_error_code(future_errc::broken_promise)) 216 )); 217 #endif // _LIBCPP_NO_EXCEPTIONS 218 __state_->__release_shared(); 219 } 220 } 221 222 future<void> 223 promise<void>::get_future() 224 { 225 if (__state_ == nullptr) 226 __throw_future_error(future_errc::no_state); 227 return future<void>(__state_); 228 } 229 230 void 231 promise<void>::set_value() 232 { 233 if (__state_ == nullptr) 234 __throw_future_error(future_errc::no_state); 235 __state_->set_value(); 236 } 237 238 void 239 promise<void>::set_exception(exception_ptr __p) 240 { 241 if (__state_ == nullptr) 242 __throw_future_error(future_errc::no_state); 243 __state_->set_exception(__p); 244 } 245 246 void 247 promise<void>::set_value_at_thread_exit() 248 { 249 if (__state_ == nullptr) 250 __throw_future_error(future_errc::no_state); 251 __state_->set_value_at_thread_exit(); 252 } 253 254 void 255 promise<void>::set_exception_at_thread_exit(exception_ptr __p) 256 { 257 if (__state_ == nullptr) 258 __throw_future_error(future_errc::no_state); 259 __state_->set_exception_at_thread_exit(__p); 260 } 261 262 shared_future<void>::~shared_future() 263 { 264 if (__state_) 265 __state_->__release_shared(); 266 } 267 268 shared_future<void>& 269 shared_future<void>::operator=(const shared_future& __rhs) 270 { 271 if (__rhs.__state_) 272 __rhs.__state_->__add_shared(); 273 if (__state_) 274 __state_->__release_shared(); 275 __state_ = __rhs.__state_; 276 return *this; 277 } 278 279 _LIBCPP_END_NAMESPACE_STD 280 281 #endif // !_LIBCPP_HAS_NO_THREADS 282