master
  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-exception
  6//
  7//===----------------------------------------------------------------------===//
  8
  9#include <future>
 10#include <string>
 11
 12_LIBCPP_BEGIN_NAMESPACE_STD
 13
 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_PUSH
 23_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_POP
 45
 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    } else
120      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_EXCEPTIONS
146    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_EXCEPTIONS
149    __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_STD