brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · 7bba635 Raw
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