1227825Stheraven//===------------------------- future.cpp ---------------------------------===// 2227825Stheraven// 3227825Stheraven// The LLVM Compiler Infrastructure 4227825Stheraven// 5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 6227825Stheraven// Source Licenses. See LICENSE.TXT for details. 7227825Stheraven// 8227825Stheraven//===----------------------------------------------------------------------===// 9227825Stheraven 10227825Stheraven#include "future" 11227825Stheraven#include "string" 12227825Stheraven 13227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 14227825Stheraven 15227825Stheravenclass _LIBCPP_HIDDEN __future_error_category 16227825Stheraven : public __do_message 17227825Stheraven{ 18227825Stheravenpublic: 19227825Stheraven virtual const char* name() const _NOEXCEPT; 20227825Stheraven virtual string message(int ev) const; 21227825Stheraven}; 22227825Stheraven 23227825Stheravenconst char* 24227825Stheraven__future_error_category::name() const _NOEXCEPT 25227825Stheraven{ 26227825Stheraven return "future"; 27227825Stheraven} 28227825Stheraven 29227825Stheravenstring 30227825Stheraven__future_error_category::message(int ev) const 31227825Stheraven{ 32232950Stheraven switch (static_cast<future_errc>(ev)) 33227825Stheraven { 34227825Stheraven case future_errc::broken_promise: 35227825Stheraven return string("The associated promise has been destructed prior " 36227825Stheraven "to the associated state becoming ready."); 37227825Stheraven case future_errc::future_already_retrieved: 38227825Stheraven return string("The future has already been retrieved from " 39227825Stheraven "the promise or packaged_task."); 40227825Stheraven case future_errc::promise_already_satisfied: 41227825Stheraven return string("The state of the promise has already been set."); 42227825Stheraven case future_errc::no_state: 43227825Stheraven return string("Operation not permitted on an object without " 44227825Stheraven "an associated state."); 45227825Stheraven } 46227825Stheraven return string("unspecified future_errc value\n"); 47227825Stheraven} 48227825Stheraven 49227825Stheravenconst error_category& 50241903Sdimfuture_category() _NOEXCEPT 51227825Stheraven{ 52227825Stheraven static __future_error_category __f; 53227825Stheraven return __f; 54227825Stheraven} 55227825Stheraven 56227825Stheravenfuture_error::future_error(error_code __ec) 57227825Stheraven : logic_error(__ec.message()), 58227825Stheraven __ec_(__ec) 59227825Stheraven{ 60227825Stheraven} 61227825Stheraven 62227825Stheravenfuture_error::~future_error() _NOEXCEPT 63227825Stheraven{ 64227825Stheraven} 65227825Stheraven 66227825Stheravenvoid 67227825Stheraven__assoc_sub_state::__on_zero_shared() _NOEXCEPT 68227825Stheraven{ 69227825Stheraven delete this; 70227825Stheraven} 71227825Stheraven 72227825Stheravenvoid 73227825Stheraven__assoc_sub_state::set_value() 74227825Stheraven{ 75227825Stheraven unique_lock<mutex> __lk(__mut_); 76227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 77227825Stheraven if (__has_value()) 78227825Stheraven throw future_error(make_error_code(future_errc::promise_already_satisfied)); 79227825Stheraven#endif 80227825Stheraven __state_ |= __constructed | ready; 81246487Stheraven __cv_.notify_all(); 82227825Stheraven __lk.unlock(); 83227825Stheraven} 84227825Stheraven 85227825Stheravenvoid 86227825Stheraven__assoc_sub_state::set_value_at_thread_exit() 87227825Stheraven{ 88227825Stheraven unique_lock<mutex> __lk(__mut_); 89227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 90227825Stheraven if (__has_value()) 91227825Stheraven throw future_error(make_error_code(future_errc::promise_already_satisfied)); 92227825Stheraven#endif 93227825Stheraven __state_ |= __constructed; 94227825Stheraven __thread_local_data()->__make_ready_at_thread_exit(this); 95227825Stheraven __lk.unlock(); 96227825Stheraven} 97227825Stheraven 98227825Stheravenvoid 99227825Stheraven__assoc_sub_state::set_exception(exception_ptr __p) 100227825Stheraven{ 101227825Stheraven unique_lock<mutex> __lk(__mut_); 102227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 103227825Stheraven if (__has_value()) 104227825Stheraven throw future_error(make_error_code(future_errc::promise_already_satisfied)); 105227825Stheraven#endif 106227825Stheraven __exception_ = __p; 107227825Stheraven __state_ |= ready; 108227825Stheraven __lk.unlock(); 109227825Stheraven __cv_.notify_all(); 110227825Stheraven} 111227825Stheraven 112227825Stheravenvoid 113227825Stheraven__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) 114227825Stheraven{ 115227825Stheraven unique_lock<mutex> __lk(__mut_); 116227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 117227825Stheraven if (__has_value()) 118227825Stheraven throw future_error(make_error_code(future_errc::promise_already_satisfied)); 119227825Stheraven#endif 120227825Stheraven __exception_ = __p; 121227825Stheraven __thread_local_data()->__make_ready_at_thread_exit(this); 122227825Stheraven __lk.unlock(); 123227825Stheraven} 124227825Stheraven 125227825Stheravenvoid 126227825Stheraven__assoc_sub_state::__make_ready() 127227825Stheraven{ 128227825Stheraven unique_lock<mutex> __lk(__mut_); 129227825Stheraven __state_ |= ready; 130227825Stheraven __lk.unlock(); 131227825Stheraven __cv_.notify_all(); 132227825Stheraven} 133227825Stheraven 134227825Stheravenvoid 135227825Stheraven__assoc_sub_state::copy() 136227825Stheraven{ 137227825Stheraven unique_lock<mutex> __lk(__mut_); 138227825Stheraven __sub_wait(__lk); 139227825Stheraven if (__exception_ != nullptr) 140227825Stheraven rethrow_exception(__exception_); 141227825Stheraven} 142227825Stheraven 143227825Stheravenvoid 144227825Stheraven__assoc_sub_state::wait() 145227825Stheraven{ 146227825Stheraven unique_lock<mutex> __lk(__mut_); 147227825Stheraven __sub_wait(__lk); 148227825Stheraven} 149227825Stheraven 150227825Stheravenvoid 151227825Stheraven__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) 152227825Stheraven{ 153227825Stheraven if (!__is_ready()) 154227825Stheraven { 155232950Stheraven if (__state_ & static_cast<unsigned>(deferred)) 156227825Stheraven { 157232950Stheraven __state_ &= ~static_cast<unsigned>(deferred); 158227825Stheraven __lk.unlock(); 159227825Stheraven __execute(); 160227825Stheraven } 161227825Stheraven else 162227825Stheraven while (!__is_ready()) 163227825Stheraven __cv_.wait(__lk); 164227825Stheraven } 165227825Stheraven} 166227825Stheraven 167227825Stheravenvoid 168227825Stheraven__assoc_sub_state::__execute() 169227825Stheraven{ 170227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 171227825Stheraven throw future_error(make_error_code(future_errc::no_state)); 172227825Stheraven#endif 173227825Stheraven} 174227825Stheraven 175227825Stheravenfuture<void>::future(__assoc_sub_state* __state) 176227825Stheraven : __state_(__state) 177227825Stheraven{ 178227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 179227825Stheraven if (__state_->__has_future_attached()) 180227825Stheraven throw future_error(make_error_code(future_errc::future_already_retrieved)); 181227825Stheraven#endif 182227825Stheraven __state_->__add_shared(); 183227825Stheraven __state_->__set_future_attached(); 184227825Stheraven} 185227825Stheraven 186227825Stheravenfuture<void>::~future() 187227825Stheraven{ 188227825Stheraven if (__state_) 189227825Stheraven __state_->__release_shared(); 190227825Stheraven} 191227825Stheraven 192227825Stheravenvoid 193227825Stheravenfuture<void>::get() 194227825Stheraven{ 195227825Stheraven unique_ptr<__shared_count, __release_shared_count> __(__state_); 196227825Stheraven __assoc_sub_state* __s = __state_; 197227825Stheraven __state_ = nullptr; 198227825Stheraven __s->copy(); 199227825Stheraven} 200227825Stheraven 201227825Stheravenpromise<void>::promise() 202227825Stheraven : __state_(new __assoc_sub_state) 203227825Stheraven{ 204227825Stheraven} 205227825Stheraven 206227825Stheravenpromise<void>::~promise() 207227825Stheraven{ 208227825Stheraven if (__state_) 209227825Stheraven { 210227825Stheraven if (!__state_->__has_value() && __state_->use_count() > 1) 211227825Stheraven __state_->set_exception(make_exception_ptr( 212227825Stheraven future_error(make_error_code(future_errc::broken_promise)) 213227825Stheraven )); 214227825Stheraven __state_->__release_shared(); 215227825Stheraven } 216227825Stheraven} 217227825Stheraven 218227825Stheravenfuture<void> 219227825Stheravenpromise<void>::get_future() 220227825Stheraven{ 221227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 222227825Stheraven if (__state_ == nullptr) 223227825Stheraven throw future_error(make_error_code(future_errc::no_state)); 224227825Stheraven#endif 225227825Stheraven return future<void>(__state_); 226227825Stheraven} 227227825Stheraven 228227825Stheravenvoid 229227825Stheravenpromise<void>::set_value() 230227825Stheraven{ 231227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 232227825Stheraven if (__state_ == nullptr) 233227825Stheraven throw future_error(make_error_code(future_errc::no_state)); 234227825Stheraven#endif 235227825Stheraven __state_->set_value(); 236227825Stheraven} 237227825Stheraven 238227825Stheravenvoid 239227825Stheravenpromise<void>::set_exception(exception_ptr __p) 240227825Stheraven{ 241227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 242227825Stheraven if (__state_ == nullptr) 243227825Stheraven throw future_error(make_error_code(future_errc::no_state)); 244227825Stheraven#endif 245227825Stheraven __state_->set_exception(__p); 246227825Stheraven} 247227825Stheraven 248227825Stheravenvoid 249227825Stheravenpromise<void>::set_value_at_thread_exit() 250227825Stheraven{ 251227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 252227825Stheraven if (__state_ == nullptr) 253227825Stheraven throw future_error(make_error_code(future_errc::no_state)); 254227825Stheraven#endif 255227825Stheraven __state_->set_value_at_thread_exit(); 256227825Stheraven} 257227825Stheraven 258227825Stheravenvoid 259227825Stheravenpromise<void>::set_exception_at_thread_exit(exception_ptr __p) 260227825Stheraven{ 261227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 262227825Stheraven if (__state_ == nullptr) 263227825Stheraven throw future_error(make_error_code(future_errc::no_state)); 264227825Stheraven#endif 265227825Stheraven __state_->set_exception_at_thread_exit(__p); 266227825Stheraven} 267227825Stheraven 268227825Stheravenshared_future<void>::~shared_future() 269227825Stheraven{ 270227825Stheraven if (__state_) 271227825Stheraven __state_->__release_shared(); 272227825Stheraven} 273227825Stheraven 274227825Stheravenshared_future<void>& 275227825Stheravenshared_future<void>::operator=(const shared_future& __rhs) 276227825Stheraven{ 277227825Stheraven if (__rhs.__state_) 278227825Stheraven __rhs.__state_->__add_shared(); 279227825Stheraven if (__state_) 280227825Stheraven __state_->__release_shared(); 281227825Stheraven __state_ = __rhs.__state_; 282227825Stheraven return *this; 283227825Stheraven} 284227825Stheraven 285227825Stheraven_LIBCPP_END_NAMESPACE_STD 286