diff options
author | 2021-01-02 20:29:13 +0000 | |
---|---|---|
committer | 2021-01-02 20:29:13 +0000 | |
commit | 46035553bfdd96e63c94e32da0210227ec2e3cf1 (patch) | |
tree | b191f708fb9a2995ba745b2f31cdeeaee4872b7f /gnu/llvm/libcxx/src/future.cpp | |
parent | Move Makefiles for libc++ and libc++abi to gnu/lib in preparation for an (diff) | |
download | wireguard-openbsd-46035553bfdd96e63c94e32da0210227ec2e3cf1.tar.xz wireguard-openbsd-46035553bfdd96e63c94e32da0210227ec2e3cf1.zip |
Import libc++ 10.0.1 release.
Diffstat (limited to 'gnu/llvm/libcxx/src/future.cpp')
-rw-r--r-- | gnu/llvm/libcxx/src/future.cpp | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/gnu/llvm/libcxx/src/future.cpp b/gnu/llvm/libcxx/src/future.cpp new file mode 100644 index 00000000000..58d0b4c247c --- /dev/null +++ b/gnu/llvm/libcxx/src/future.cpp @@ -0,0 +1,277 @@ +//===------------------------- future.cpp ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "__config" + +#ifndef _LIBCPP_HAS_NO_THREADS + +#include "future" +#include "string" + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_HIDDEN __future_error_category + : public __do_message +{ +public: + virtual const char* name() const _NOEXCEPT; + virtual string message(int ev) const; +}; + +const char* +__future_error_category::name() const _NOEXCEPT +{ + return "future"; +} + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch" +#elif defined(__GNUC__) || defined(__GNUG__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch" +#endif + +string +__future_error_category::message(int ev) const +{ + switch (static_cast<future_errc>(ev)) + { + case future_errc(0): // For backwards compatibility with C++11 (LWG 2056) + case future_errc::broken_promise: + return string("The associated promise has been destructed prior " + "to the associated state becoming ready."); + case future_errc::future_already_retrieved: + return string("The future has already been retrieved from " + "the promise or packaged_task."); + case future_errc::promise_already_satisfied: + return string("The state of the promise has already been set."); + case future_errc::no_state: + return string("Operation not permitted on an object without " + "an associated state."); + } + return string("unspecified future_errc value\n"); +} + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) || defined(__GNUG__) +#pragma GCC diagnostic pop +#endif + +const error_category& +future_category() _NOEXCEPT +{ + static __future_error_category __f; + return __f; +} + +future_error::future_error(error_code __ec) + : logic_error(__ec.message()), + __ec_(__ec) +{ +} + +future_error::~future_error() _NOEXCEPT +{ +} + +void +__assoc_sub_state::__on_zero_shared() _NOEXCEPT +{ + delete this; +} + +void +__assoc_sub_state::set_value() +{ + unique_lock<mutex> __lk(__mut_); + if (__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); + __state_ |= __constructed | ready; + __cv_.notify_all(); +} + +void +__assoc_sub_state::set_value_at_thread_exit() +{ + unique_lock<mutex> __lk(__mut_); + if (__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); + __state_ |= __constructed; + __thread_local_data()->__make_ready_at_thread_exit(this); +} + +void +__assoc_sub_state::set_exception(exception_ptr __p) +{ + unique_lock<mutex> __lk(__mut_); + if (__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); + __exception_ = __p; + __state_ |= ready; + __cv_.notify_all(); +} + +void +__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) +{ + unique_lock<mutex> __lk(__mut_); + if (__has_value()) + __throw_future_error(future_errc::promise_already_satisfied); + __exception_ = __p; + __thread_local_data()->__make_ready_at_thread_exit(this); +} + +void +__assoc_sub_state::__make_ready() +{ + unique_lock<mutex> __lk(__mut_); + __state_ |= ready; + __cv_.notify_all(); +} + +void +__assoc_sub_state::copy() +{ + unique_lock<mutex> __lk(__mut_); + __sub_wait(__lk); + if (__exception_ != nullptr) + rethrow_exception(__exception_); +} + +void +__assoc_sub_state::wait() +{ + unique_lock<mutex> __lk(__mut_); + __sub_wait(__lk); +} + +void +__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) +{ + if (!__is_ready()) + { + if (__state_ & static_cast<unsigned>(deferred)) + { + __state_ &= ~static_cast<unsigned>(deferred); + __lk.unlock(); + __execute(); + } + else + while (!__is_ready()) + __cv_.wait(__lk); + } +} + +void +__assoc_sub_state::__execute() +{ + __throw_future_error(future_errc::no_state); +} + +future<void>::future(__assoc_sub_state* __state) + : __state_(__state) +{ + __state_->__attach_future(); +} + +future<void>::~future() +{ + if (__state_) + __state_->__release_shared(); +} + +void +future<void>::get() +{ + unique_ptr<__shared_count, __release_shared_count> __(__state_); + __assoc_sub_state* __s = __state_; + __state_ = nullptr; + __s->copy(); +} + +promise<void>::promise() + : __state_(new __assoc_sub_state) +{ +} + +promise<void>::~promise() +{ + if (__state_) + { +#ifndef _LIBCPP_NO_EXCEPTIONS + if (!__state_->__has_value() && __state_->use_count() > 1) + __state_->set_exception(make_exception_ptr( + future_error(make_error_code(future_errc::broken_promise)) + )); +#endif // _LIBCPP_NO_EXCEPTIONS + __state_->__release_shared(); + } +} + +future<void> +promise<void>::get_future() +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + return future<void>(__state_); +} + +void +promise<void>::set_value() +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_value(); +} + +void +promise<void>::set_exception(exception_ptr __p) +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_exception(__p); +} + +void +promise<void>::set_value_at_thread_exit() +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_value_at_thread_exit(); +} + +void +promise<void>::set_exception_at_thread_exit(exception_ptr __p) +{ + if (__state_ == nullptr) + __throw_future_error(future_errc::no_state); + __state_->set_exception_at_thread_exit(__p); +} + +shared_future<void>::~shared_future() +{ + if (__state_) + __state_->__release_shared(); +} + +shared_future<void>& +shared_future<void>::operator=(const shared_future& __rhs) +{ + if (__rhs.__state_) + __rhs.__state_->__add_shared(); + if (__state_) + __state_->__release_shared(); + __state_ = __rhs.__state_; + return *this; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !_LIBCPP_HAS_NO_THREADS |