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