198 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <future>10#include <string>11 12_LIBCPP_BEGIN_NAMESPACE_STD13 14class _LIBCPP_HIDDEN __future_error_category : public __do_message {15public:16 virtual const char* name() const noexcept;17 virtual string message(int ev) const;18};19 20const char* __future_error_category::name() const noexcept { return "future"; }21 22_LIBCPP_DIAGNOSTIC_PUSH23_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")24_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")25 26string __future_error_category::message(int ev) const {27 switch (static_cast<future_errc>(ev)) {28 case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)29 case future_errc::broken_promise:30 return string("The associated promise has been destructed prior "31 "to the associated state becoming ready.");32 case future_errc::future_already_retrieved:33 return string("The future has already been retrieved from "34 "the promise or packaged_task.");35 case future_errc::promise_already_satisfied:36 return string("The state of the promise has already been set.");37 case future_errc::no_state:38 return string("Operation not permitted on an object without "39 "an associated state.");40 }41 return string("unspecified future_errc value\n");42}43 44_LIBCPP_DIAGNOSTIC_POP45 46const error_category& future_category() noexcept {47 union AvoidDestroyingFutureCategory {48 __future_error_category future_error_category;49 constexpr explicit AvoidDestroyingFutureCategory() : future_error_category() {}50 ~AvoidDestroyingFutureCategory() {}51 };52 constinit static AvoidDestroyingFutureCategory helper;53 return helper.future_error_category;54}55 56future_error::future_error(error_code __ec) : logic_error(__ec.message()), __ec_(__ec) {}57 58future_error::~future_error() noexcept {}59 60void __assoc_sub_state::__on_zero_shared() noexcept { delete this; }61 62void __assoc_sub_state::set_value() {63 unique_lock<mutex> __lk(__mut_);64 if (__has_value())65 std::__throw_future_error(future_errc::promise_already_satisfied);66 __state_ |= __constructed | ready;67 __cv_.notify_all();68}69 70void __assoc_sub_state::set_value_at_thread_exit() {71 unique_lock<mutex> __lk(__mut_);72 if (__has_value())73 std::__throw_future_error(future_errc::promise_already_satisfied);74 __state_ |= __constructed;75 __thread_local_data()->__make_ready_at_thread_exit(this);76}77 78void __assoc_sub_state::set_exception(exception_ptr __p) {79 unique_lock<mutex> __lk(__mut_);80 if (__has_value())81 std::__throw_future_error(future_errc::promise_already_satisfied);82 __exception_ = __p;83 __state_ |= ready;84 __cv_.notify_all();85}86 87void __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) {88 unique_lock<mutex> __lk(__mut_);89 if (__has_value())90 std::__throw_future_error(future_errc::promise_already_satisfied);91 __exception_ = __p;92 __thread_local_data()->__make_ready_at_thread_exit(this);93}94 95void __assoc_sub_state::__make_ready() {96 unique_lock<mutex> __lk(__mut_);97 __state_ |= ready;98 __cv_.notify_all();99}100 101void __assoc_sub_state::copy() {102 unique_lock<mutex> __lk(__mut_);103 __sub_wait(__lk);104 if (__exception_ != nullptr)105 rethrow_exception(__exception_);106}107 108void __assoc_sub_state::wait() {109 unique_lock<mutex> __lk(__mut_);110 __sub_wait(__lk);111}112 113void __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) {114 if (!__is_ready()) {115 if (__state_ & static_cast<unsigned>(deferred)) {116 __state_ &= ~static_cast<unsigned>(deferred);117 __lk.unlock();118 __execute();119 } else120 while (!__is_ready())121 __cv_.wait(__lk);122 }123}124 125void __assoc_sub_state::__execute() { std::__throw_future_error(future_errc::no_state); }126 127future<void>::future(__assoc_sub_state* __state) : __state_(__state) { __state_->__attach_future(); }128 129future<void>::~future() {130 if (__state_)131 __state_->__release_shared();132}133 134void future<void>::get() {135 unique_ptr<__shared_count, __release_shared_count> __(__state_);136 __assoc_sub_state* __s = __state_;137 __state_ = nullptr;138 __s->copy();139}140 141promise<void>::promise() : __state_(new __assoc_sub_state) {}142 143promise<void>::~promise() {144 if (__state_) {145#if _LIBCPP_HAS_EXCEPTIONS146 if (!__state_->__has_value() && __state_->use_count() > 1)147 __state_->set_exception(make_exception_ptr(future_error(future_errc::broken_promise)));148#endif // _LIBCPP_HAS_EXCEPTIONS149 __state_->__release_shared();150 }151}152 153future<void> promise<void>::get_future() {154 if (__state_ == nullptr)155 std::__throw_future_error(future_errc::no_state);156 return future<void>(__state_);157}158 159void promise<void>::set_value() {160 if (__state_ == nullptr)161 std::__throw_future_error(future_errc::no_state);162 __state_->set_value();163}164 165void promise<void>::set_exception(exception_ptr __p) {166 if (__state_ == nullptr)167 std::__throw_future_error(future_errc::no_state);168 __state_->set_exception(__p);169}170 171void promise<void>::set_value_at_thread_exit() {172 if (__state_ == nullptr)173 std::__throw_future_error(future_errc::no_state);174 __state_->set_value_at_thread_exit();175}176 177void promise<void>::set_exception_at_thread_exit(exception_ptr __p) {178 if (__state_ == nullptr)179 std::__throw_future_error(future_errc::no_state);180 __state_->set_exception_at_thread_exit(__p);181}182 183shared_future<void>::~shared_future() {184 if (__state_)185 __state_->__release_shared();186}187 188shared_future<void>& shared_future<void>::operator=(const shared_future& __rhs) {189 if (__rhs.__state_)190 __rhs.__state_->__add_shared();191 if (__state_)192 __state_->__release_shared();193 __state_ = __rhs.__state_;194 return *this;195}196 197_LIBCPP_END_NAMESPACE_STD198