Path: blob/main/contrib/llvm-project/libcxx/src/future.cpp
35147 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <future>9#include <string>1011_LIBCPP_BEGIN_NAMESPACE_STD1213class _LIBCPP_HIDDEN __future_error_category : public __do_message {14public:15virtual const char* name() const noexcept;16virtual string message(int ev) const;17};1819const char* __future_error_category::name() const noexcept { return "future"; }2021_LIBCPP_DIAGNOSTIC_PUSH22_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")23_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")2425string __future_error_category::message(int ev) const {26switch (static_cast<future_errc>(ev)) {27case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)28case future_errc::broken_promise:29return string("The associated promise has been destructed prior "30"to the associated state becoming ready.");31case future_errc::future_already_retrieved:32return string("The future has already been retrieved from "33"the promise or packaged_task.");34case future_errc::promise_already_satisfied:35return string("The state of the promise has already been set.");36case future_errc::no_state:37return string("Operation not permitted on an object without "38"an associated state.");39}40return string("unspecified future_errc value\n");41}4243_LIBCPP_DIAGNOSTIC_POP4445const error_category& future_category() noexcept {46union AvoidDestroyingFutureCategory {47__future_error_category future_error_category;48constexpr explicit AvoidDestroyingFutureCategory() : future_error_category() {}49~AvoidDestroyingFutureCategory() {}50};51constinit static AvoidDestroyingFutureCategory helper;52return helper.future_error_category;53}5455future_error::future_error(error_code __ec) : logic_error(__ec.message()), __ec_(__ec) {}5657future_error::~future_error() noexcept {}5859void __assoc_sub_state::__on_zero_shared() noexcept { delete this; }6061void __assoc_sub_state::set_value() {62unique_lock<mutex> __lk(__mut_);63if (__has_value())64__throw_future_error(future_errc::promise_already_satisfied);65__state_ |= __constructed | ready;66__cv_.notify_all();67}6869void __assoc_sub_state::set_value_at_thread_exit() {70unique_lock<mutex> __lk(__mut_);71if (__has_value())72__throw_future_error(future_errc::promise_already_satisfied);73__state_ |= __constructed;74__thread_local_data()->__make_ready_at_thread_exit(this);75}7677void __assoc_sub_state::set_exception(exception_ptr __p) {78unique_lock<mutex> __lk(__mut_);79if (__has_value())80__throw_future_error(future_errc::promise_already_satisfied);81__exception_ = __p;82__state_ |= ready;83__cv_.notify_all();84}8586void __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) {87unique_lock<mutex> __lk(__mut_);88if (__has_value())89__throw_future_error(future_errc::promise_already_satisfied);90__exception_ = __p;91__thread_local_data()->__make_ready_at_thread_exit(this);92}9394void __assoc_sub_state::__make_ready() {95unique_lock<mutex> __lk(__mut_);96__state_ |= ready;97__cv_.notify_all();98}99100void __assoc_sub_state::copy() {101unique_lock<mutex> __lk(__mut_);102__sub_wait(__lk);103if (__exception_ != nullptr)104rethrow_exception(__exception_);105}106107void __assoc_sub_state::wait() {108unique_lock<mutex> __lk(__mut_);109__sub_wait(__lk);110}111112void __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) {113if (!__is_ready()) {114if (__state_ & static_cast<unsigned>(deferred)) {115__state_ &= ~static_cast<unsigned>(deferred);116__lk.unlock();117__execute();118} else119while (!__is_ready())120__cv_.wait(__lk);121}122}123124void __assoc_sub_state::__execute() { __throw_future_error(future_errc::no_state); }125126future<void>::future(__assoc_sub_state* __state) : __state_(__state) { __state_->__attach_future(); }127128future<void>::~future() {129if (__state_)130__state_->__release_shared();131}132133void future<void>::get() {134unique_ptr<__shared_count, __release_shared_count> __(__state_);135__assoc_sub_state* __s = __state_;136__state_ = nullptr;137__s->copy();138}139140promise<void>::promise() : __state_(new __assoc_sub_state) {}141142promise<void>::~promise() {143if (__state_) {144#ifndef _LIBCPP_HAS_NO_EXCEPTIONS145if (!__state_->__has_value() && __state_->use_count() > 1)146__state_->set_exception(make_exception_ptr(future_error(future_errc::broken_promise)));147#endif // _LIBCPP_HAS_NO_EXCEPTIONS148__state_->__release_shared();149}150}151152future<void> promise<void>::get_future() {153if (__state_ == nullptr)154__throw_future_error(future_errc::no_state);155return future<void>(__state_);156}157158void promise<void>::set_value() {159if (__state_ == nullptr)160__throw_future_error(future_errc::no_state);161__state_->set_value();162}163164void promise<void>::set_exception(exception_ptr __p) {165if (__state_ == nullptr)166__throw_future_error(future_errc::no_state);167__state_->set_exception(__p);168}169170void promise<void>::set_value_at_thread_exit() {171if (__state_ == nullptr)172__throw_future_error(future_errc::no_state);173__state_->set_value_at_thread_exit();174}175176void promise<void>::set_exception_at_thread_exit(exception_ptr __p) {177if (__state_ == nullptr)178__throw_future_error(future_errc::no_state);179__state_->set_exception_at_thread_exit(__p);180}181182shared_future<void>::~shared_future() {183if (__state_)184__state_->__release_shared();185}186187shared_future<void>& shared_future<void>::operator=(const shared_future& __rhs) {188if (__rhs.__state_)189__rhs.__state_->__add_shared();190if (__state_)191__state_->__release_shared();192__state_ = __rhs.__state_;193return *this;194}195196_LIBCPP_END_NAMESPACE_STD197198199