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#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 37string 38__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 64const error_category& 65future_category() _NOEXCEPT 66{ 67 static __future_error_category __f; 68 return __f; 69} 70 71future_error::future_error(error_code __ec) 72 : logic_error(__ec.message()), 73 __ec_(__ec) 74{ 75} 76 77future_error::~future_error() _NOEXCEPT 78{ 79} 80 81void 82__assoc_sub_state::__on_zero_shared() _NOEXCEPT 83{ 84 delete this; 85} 86 87void 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 100void 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 113void 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 127void 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 140void 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 149void 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 158void 159__assoc_sub_state::wait() 160{ 161 unique_lock<mutex> __lk(__mut_); 162 __sub_wait(__lk); 163} 164 165void 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 182void 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 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 201future<void>::~future() 202{ 203 if (__state_) 204 __state_->__release_shared(); 205} 206 207void 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 216promise<void>::promise() 217 : __state_(new __assoc_sub_state) 218{ 219} 220 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 233future<void> 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 243void 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 253void 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 263void 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 273void 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 283shared_future<void>::~shared_future() 284{ 285 if (__state_) 286 __state_->__release_shared(); 287} 288 289shared_future<void>& 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