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