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