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 9*81ad6265SDimitry Andric #include <__config> 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS 120b57cec5SDimitry Andric 13*81ad6265SDimitry Andric #include <future> 14*81ad6265SDimitry Andric #include <string> 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric class _LIBCPP_HIDDEN __future_error_category 190b57cec5SDimitry Andric : public __do_message 200b57cec5SDimitry Andric { 210b57cec5SDimitry Andric public: 22fe6060f1SDimitry Andric virtual const char* name() const noexcept; 230b57cec5SDimitry Andric virtual string message(int ev) const; 240b57cec5SDimitry Andric }; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric const char* 27fe6060f1SDimitry Andric __future_error_category::name() const noexcept 280b57cec5SDimitry Andric { 290b57cec5SDimitry Andric return "future"; 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 32*81ad6265SDimitry Andric _LIBCPP_DIAGNOSTIC_PUSH 33*81ad6265SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch") 34*81ad6265SDimitry Andric _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch") 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric string 370b57cec5SDimitry Andric __future_error_category::message(int ev) const 380b57cec5SDimitry Andric { 390b57cec5SDimitry Andric switch (static_cast<future_errc>(ev)) 400b57cec5SDimitry Andric { 410b57cec5SDimitry Andric case future_errc(0): // For backwards compatibility with C++11 (LWG 2056) 420b57cec5SDimitry Andric case future_errc::broken_promise: 430b57cec5SDimitry Andric return string("The associated promise has been destructed prior " 440b57cec5SDimitry Andric "to the associated state becoming ready."); 450b57cec5SDimitry Andric case future_errc::future_already_retrieved: 460b57cec5SDimitry Andric return string("The future has already been retrieved from " 470b57cec5SDimitry Andric "the promise or packaged_task."); 480b57cec5SDimitry Andric case future_errc::promise_already_satisfied: 490b57cec5SDimitry Andric return string("The state of the promise has already been set."); 500b57cec5SDimitry Andric case future_errc::no_state: 510b57cec5SDimitry Andric return string("Operation not permitted on an object without " 520b57cec5SDimitry Andric "an associated state."); 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric return string("unspecified future_errc value\n"); 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 57*81ad6265SDimitry Andric _LIBCPP_DIAGNOSTIC_POP 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric const error_category& 60fe6060f1SDimitry Andric future_category() noexcept 610b57cec5SDimitry Andric { 620b57cec5SDimitry Andric static __future_error_category __f; 630b57cec5SDimitry Andric return __f; 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric future_error::future_error(error_code __ec) 670b57cec5SDimitry Andric : logic_error(__ec.message()), 680b57cec5SDimitry Andric __ec_(__ec) 690b57cec5SDimitry Andric { 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 72fe6060f1SDimitry Andric future_error::~future_error() noexcept 730b57cec5SDimitry Andric { 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric void 77fe6060f1SDimitry Andric __assoc_sub_state::__on_zero_shared() noexcept 780b57cec5SDimitry Andric { 790b57cec5SDimitry Andric delete this; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric void 830b57cec5SDimitry Andric __assoc_sub_state::set_value() 840b57cec5SDimitry Andric { 850b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 860b57cec5SDimitry Andric if (__has_value()) 870b57cec5SDimitry Andric __throw_future_error(future_errc::promise_already_satisfied); 880b57cec5SDimitry Andric __state_ |= __constructed | ready; 890b57cec5SDimitry Andric __cv_.notify_all(); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric void 930b57cec5SDimitry Andric __assoc_sub_state::set_value_at_thread_exit() 940b57cec5SDimitry Andric { 950b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 960b57cec5SDimitry Andric if (__has_value()) 970b57cec5SDimitry Andric __throw_future_error(future_errc::promise_already_satisfied); 980b57cec5SDimitry Andric __state_ |= __constructed; 990b57cec5SDimitry Andric __thread_local_data()->__make_ready_at_thread_exit(this); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric void 1030b57cec5SDimitry Andric __assoc_sub_state::set_exception(exception_ptr __p) 1040b57cec5SDimitry Andric { 1050b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 1060b57cec5SDimitry Andric if (__has_value()) 1070b57cec5SDimitry Andric __throw_future_error(future_errc::promise_already_satisfied); 1080b57cec5SDimitry Andric __exception_ = __p; 1090b57cec5SDimitry Andric __state_ |= ready; 1100b57cec5SDimitry Andric __cv_.notify_all(); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric void 1140b57cec5SDimitry Andric __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) 1150b57cec5SDimitry Andric { 1160b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 1170b57cec5SDimitry Andric if (__has_value()) 1180b57cec5SDimitry Andric __throw_future_error(future_errc::promise_already_satisfied); 1190b57cec5SDimitry Andric __exception_ = __p; 1200b57cec5SDimitry Andric __thread_local_data()->__make_ready_at_thread_exit(this); 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric void 1240b57cec5SDimitry Andric __assoc_sub_state::__make_ready() 1250b57cec5SDimitry Andric { 1260b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 1270b57cec5SDimitry Andric __state_ |= ready; 1280b57cec5SDimitry Andric __cv_.notify_all(); 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric void 1320b57cec5SDimitry Andric __assoc_sub_state::copy() 1330b57cec5SDimitry Andric { 1340b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 1350b57cec5SDimitry Andric __sub_wait(__lk); 1360b57cec5SDimitry Andric if (__exception_ != nullptr) 1370b57cec5SDimitry Andric rethrow_exception(__exception_); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric void 1410b57cec5SDimitry Andric __assoc_sub_state::wait() 1420b57cec5SDimitry Andric { 1430b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut_); 1440b57cec5SDimitry Andric __sub_wait(__lk); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric void 1480b57cec5SDimitry Andric __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) 1490b57cec5SDimitry Andric { 1500b57cec5SDimitry Andric if (!__is_ready()) 1510b57cec5SDimitry Andric { 1520b57cec5SDimitry Andric if (__state_ & static_cast<unsigned>(deferred)) 1530b57cec5SDimitry Andric { 1540b57cec5SDimitry Andric __state_ &= ~static_cast<unsigned>(deferred); 1550b57cec5SDimitry Andric __lk.unlock(); 1560b57cec5SDimitry Andric __execute(); 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric else 1590b57cec5SDimitry Andric while (!__is_ready()) 1600b57cec5SDimitry Andric __cv_.wait(__lk); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric void 1650b57cec5SDimitry Andric __assoc_sub_state::__execute() 1660b57cec5SDimitry Andric { 1670b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric future<void>::future(__assoc_sub_state* __state) 1710b57cec5SDimitry Andric : __state_(__state) 1720b57cec5SDimitry Andric { 1730b57cec5SDimitry Andric __state_->__attach_future(); 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric future<void>::~future() 1770b57cec5SDimitry Andric { 1780b57cec5SDimitry Andric if (__state_) 1790b57cec5SDimitry Andric __state_->__release_shared(); 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric void 1830b57cec5SDimitry Andric future<void>::get() 1840b57cec5SDimitry Andric { 1850b57cec5SDimitry Andric unique_ptr<__shared_count, __release_shared_count> __(__state_); 1860b57cec5SDimitry Andric __assoc_sub_state* __s = __state_; 1870b57cec5SDimitry Andric __state_ = nullptr; 1880b57cec5SDimitry Andric __s->copy(); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric promise<void>::promise() 1920b57cec5SDimitry Andric : __state_(new __assoc_sub_state) 1930b57cec5SDimitry Andric { 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric promise<void>::~promise() 1970b57cec5SDimitry Andric { 1980b57cec5SDimitry Andric if (__state_) 1990b57cec5SDimitry Andric { 2000b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS 2010b57cec5SDimitry Andric if (!__state_->__has_value() && __state_->use_count() > 1) 2020b57cec5SDimitry Andric __state_->set_exception(make_exception_ptr( 2030b57cec5SDimitry Andric future_error(make_error_code(future_errc::broken_promise)) 2040b57cec5SDimitry Andric )); 2050b57cec5SDimitry Andric #endif // _LIBCPP_NO_EXCEPTIONS 2060b57cec5SDimitry Andric __state_->__release_shared(); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric future<void> 2110b57cec5SDimitry Andric promise<void>::get_future() 2120b57cec5SDimitry Andric { 2130b57cec5SDimitry Andric if (__state_ == nullptr) 2140b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 2150b57cec5SDimitry Andric return future<void>(__state_); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric void 2190b57cec5SDimitry Andric promise<void>::set_value() 2200b57cec5SDimitry Andric { 2210b57cec5SDimitry Andric if (__state_ == nullptr) 2220b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 2230b57cec5SDimitry Andric __state_->set_value(); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric void 2270b57cec5SDimitry Andric promise<void>::set_exception(exception_ptr __p) 2280b57cec5SDimitry Andric { 2290b57cec5SDimitry Andric if (__state_ == nullptr) 2300b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 2310b57cec5SDimitry Andric __state_->set_exception(__p); 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric void 2350b57cec5SDimitry Andric promise<void>::set_value_at_thread_exit() 2360b57cec5SDimitry Andric { 2370b57cec5SDimitry Andric if (__state_ == nullptr) 2380b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 2390b57cec5SDimitry Andric __state_->set_value_at_thread_exit(); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric void 2430b57cec5SDimitry Andric promise<void>::set_exception_at_thread_exit(exception_ptr __p) 2440b57cec5SDimitry Andric { 2450b57cec5SDimitry Andric if (__state_ == nullptr) 2460b57cec5SDimitry Andric __throw_future_error(future_errc::no_state); 2470b57cec5SDimitry Andric __state_->set_exception_at_thread_exit(__p); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric shared_future<void>::~shared_future() 2510b57cec5SDimitry Andric { 2520b57cec5SDimitry Andric if (__state_) 2530b57cec5SDimitry Andric __state_->__release_shared(); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric shared_future<void>& 2570b57cec5SDimitry Andric shared_future<void>::operator=(const shared_future& __rhs) 2580b57cec5SDimitry Andric { 2590b57cec5SDimitry Andric if (__rhs.__state_) 2600b57cec5SDimitry Andric __rhs.__state_->__add_shared(); 2610b57cec5SDimitry Andric if (__state_) 2620b57cec5SDimitry Andric __state_->__release_shared(); 2630b57cec5SDimitry Andric __state_ = __rhs.__state_; 2640b57cec5SDimitry Andric return *this; 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric #endif // !_LIBCPP_HAS_NO_THREADS 270