1349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 981ad6265SDimitry Andric #include <future> 1081ad6265SDimitry Andric #include <string> 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 130b57cec5SDimitry Andric 14*cb14a3feSDimitry Andric class _LIBCPP_HIDDEN __future_error_category : public __do_message { 150b57cec5SDimitry Andric public: 16fe6060f1SDimitry Andric virtual const char* name() const noexcept; 170b57cec5SDimitry Andric virtual string message(int ev) const; 180b57cec5SDimitry Andric }; 190b57cec5SDimitry Andric 20*cb14a3feSDimitry Andric const char* __future_error_category::name() const noexcept { return "future"; } 210b57cec5SDimitry Andric 2281ad6265SDimitry Andric _LIBCPP_DIAGNOSTIC_PUSH 2381ad6265SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch") 2481ad6265SDimitry Andric _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch") 250b57cec5SDimitry Andric 26*cb14a3feSDimitry Andric string __future_error_category::message(int ev) const { 27*cb14a3feSDimitry Andric switch (static_cast<future_errc>(ev)) { 280b57cec5SDimitry Andric case future_errc(0): // For backwards compatibility with C++11 (LWG 2056) 290b57cec5SDimitry Andric case future_errc::broken_promise: 300b57cec5SDimitry Andric return string("The associated promise has been destructed prior " 310b57cec5SDimitry Andric "to the associated state becoming ready."); 320b57cec5SDimitry Andric case future_errc::future_already_retrieved: 330b57cec5SDimitry Andric return string("The future has already been retrieved from " 340b57cec5SDimitry Andric "the promise or packaged_task."); 350b57cec5SDimitry Andric case future_errc::promise_already_satisfied: 360b57cec5SDimitry Andric return string("The state of the promise has already been set."); 370b57cec5SDimitry Andric case future_errc::no_state: 380b57cec5SDimitry Andric return string("Operation not permitted on an object without " 390b57cec5SDimitry Andric "an associated state."); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric return string("unspecified future_errc value\n"); 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 4481ad6265SDimitry Andric _LIBCPP_DIAGNOSTIC_POP 450b57cec5SDimitry Andric 46*cb14a3feSDimitry Andric const error_category& future_category() noexcept { 475f757f3fSDimitry Andric union AvoidDestroyingFutureCategory { 485f757f3fSDimitry Andric __future_error_category future_error_category; 495f757f3fSDimitry Andric constexpr explicit AvoidDestroyingFutureCategory() : future_error_category() {} 505f757f3fSDimitry Andric ~AvoidDestroyingFutureCategory() {} 515f757f3fSDimitry Andric }; 525f757f3fSDimitry Andric constinit static AvoidDestroyingFutureCategory helper; 535f757f3fSDimitry Andric return helper.future_error_category; 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 56*cb14a3feSDimitry Andric future_error::future_error(error_code __ec) : logic_error(__ec.message()), __ec_(__ec) {} 570b57cec5SDimitry Andric 58*cb14a3feSDimitry Andric future_error::~future_error() noexcept {} 590b57cec5SDimitry Andric 60*cb14a3feSDimitry Andric void __assoc_sub_state::__on_zero_shared() noexcept { delete this; } 610b57cec5SDimitry Andric 62*cb14a3feSDimitry Andric void __assoc_sub_state::set_value() { 630b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 640b57cec5SDimitry Andric if (__has_value()) 650b57cec5SDimitry Andric __throw_future_error(future_errc::promise_already_satisfied); 660b57cec5SDimitry Andric __state_ |= __constructed | ready; 670b57cec5SDimitry Andric __cv_.notify_all(); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 70*cb14a3feSDimitry Andric void __assoc_sub_state::set_value_at_thread_exit() { 710b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 720b57cec5SDimitry Andric if (__has_value()) 730b57cec5SDimitry Andric __throw_future_error(future_errc::promise_already_satisfied); 740b57cec5SDimitry Andric __state_ |= __constructed; 750b57cec5SDimitry Andric __thread_local_data()->__make_ready_at_thread_exit(this); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 78*cb14a3feSDimitry Andric void __assoc_sub_state::set_exception(exception_ptr __p) { 790b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 800b57cec5SDimitry Andric if (__has_value()) 810b57cec5SDimitry Andric __throw_future_error(future_errc::promise_already_satisfied); 820b57cec5SDimitry Andric __exception_ = __p; 830b57cec5SDimitry Andric __state_ |= ready; 840b57cec5SDimitry Andric __cv_.notify_all(); 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 87*cb14a3feSDimitry Andric void __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) { 880b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 890b57cec5SDimitry Andric if (__has_value()) 900b57cec5SDimitry Andric __throw_future_error(future_errc::promise_already_satisfied); 910b57cec5SDimitry Andric __exception_ = __p; 920b57cec5SDimitry Andric __thread_local_data()->__make_ready_at_thread_exit(this); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 95*cb14a3feSDimitry Andric void __assoc_sub_state::__make_ready() { 960b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 970b57cec5SDimitry Andric __state_ |= ready; 980b57cec5SDimitry Andric __cv_.notify_all(); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 101*cb14a3feSDimitry Andric void __assoc_sub_state::copy() { 1020b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 1030b57cec5SDimitry Andric __sub_wait(__lk); 1040b57cec5SDimitry Andric if (__exception_ != nullptr) 1050b57cec5SDimitry Andric rethrow_exception(__exception_); 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 108*cb14a3feSDimitry Andric void __assoc_sub_state::wait() { 1090b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 1100b57cec5SDimitry Andric __sub_wait(__lk); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 113*cb14a3feSDimitry Andric void __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) { 114*cb14a3feSDimitry Andric if (!__is_ready()) { 115*cb14a3feSDimitry Andric if (__state_ & static_cast<unsigned>(deferred)) { 1160b57cec5SDimitry Andric __state_ &= ~static_cast<unsigned>(deferred); 1170b57cec5SDimitry Andric __lk.unlock(); 1180b57cec5SDimitry Andric __execute(); 119*cb14a3feSDimitry Andric } else 1200b57cec5SDimitry Andric while (!__is_ready()) 1210b57cec5SDimitry Andric __cv_.wait(__lk); 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 125*cb14a3feSDimitry Andric void __assoc_sub_state::__execute() { __throw_future_error(future_errc::no_state); } 1260b57cec5SDimitry Andric 127*cb14a3feSDimitry Andric future<void>::future(__assoc_sub_state* __state) : __state_(__state) { __state_->__attach_future(); } 1280b57cec5SDimitry Andric 129*cb14a3feSDimitry Andric future<void>::~future() { 1300b57cec5SDimitry Andric if (__state_) 1310b57cec5SDimitry Andric __state_->__release_shared(); 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 134*cb14a3feSDimitry Andric void future<void>::get() { 1350b57cec5SDimitry Andric unique_ptr<__shared_count, __release_shared_count> __(__state_); 1360b57cec5SDimitry Andric __assoc_sub_state* __s = __state_; 1370b57cec5SDimitry Andric __state_ = nullptr; 1380b57cec5SDimitry Andric __s->copy(); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 141*cb14a3feSDimitry Andric promise<void>::promise() : __state_(new __assoc_sub_state) {} 1420b57cec5SDimitry Andric 143*cb14a3feSDimitry Andric promise<void>::~promise() { 144*cb14a3feSDimitry Andric if (__state_) { 14506c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 1460b57cec5SDimitry Andric if (!__state_->__has_value() && __state_->use_count() > 1) 1475f757f3fSDimitry Andric __state_->set_exception(make_exception_ptr(future_error(future_errc::broken_promise))); 14806c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 1490b57cec5SDimitry Andric __state_->__release_shared(); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 153*cb14a3feSDimitry Andric future<void> promise<void>::get_future() { 1540b57cec5SDimitry Andric if (__state_ == nullptr) 1550b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 1560b57cec5SDimitry Andric return future<void>(__state_); 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 159*cb14a3feSDimitry Andric void promise<void>::set_value() { 1600b57cec5SDimitry Andric if (__state_ == nullptr) 1610b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 1620b57cec5SDimitry Andric __state_->set_value(); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 165*cb14a3feSDimitry Andric void promise<void>::set_exception(exception_ptr __p) { 1660b57cec5SDimitry Andric if (__state_ == nullptr) 1670b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 1680b57cec5SDimitry Andric __state_->set_exception(__p); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 171*cb14a3feSDimitry Andric void promise<void>::set_value_at_thread_exit() { 1720b57cec5SDimitry Andric if (__state_ == nullptr) 1730b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 1740b57cec5SDimitry Andric __state_->set_value_at_thread_exit(); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 177*cb14a3feSDimitry Andric void promise<void>::set_exception_at_thread_exit(exception_ptr __p) { 1780b57cec5SDimitry Andric if (__state_ == nullptr) 1790b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 1800b57cec5SDimitry Andric __state_->set_exception_at_thread_exit(__p); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 183*cb14a3feSDimitry Andric shared_future<void>::~shared_future() { 1840b57cec5SDimitry Andric if (__state_) 1850b57cec5SDimitry Andric __state_->__release_shared(); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 188*cb14a3feSDimitry Andric shared_future<void>& shared_future<void>::operator=(const shared_future& __rhs) { 1890b57cec5SDimitry Andric if (__rhs.__state_) 1900b57cec5SDimitry Andric __rhs.__state_->__add_shared(); 1910b57cec5SDimitry Andric if (__state_) 1920b57cec5SDimitry Andric __state_->__release_shared(); 1930b57cec5SDimitry Andric __state_ = __rhs.__state_; 1940b57cec5SDimitry Andric return *this; 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD 198