xref: /openbsd/gnu/llvm/libcxx/src/future.cpp (revision 4bdff4be)
1*4bdff4beSrobert //===----------------------------------------------------------------------===//
246035553Spatrick //
346035553Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446035553Spatrick // See https://llvm.org/LICENSE.txt for license information.
546035553Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646035553Spatrick //
746035553Spatrick //===----------------------------------------------------------------------===//
846035553Spatrick 
9*4bdff4beSrobert #include <__config>
1046035553Spatrick 
1146035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
1246035553Spatrick 
13*4bdff4beSrobert #include <future>
14*4bdff4beSrobert #include <string>
1546035553Spatrick 
1646035553Spatrick _LIBCPP_BEGIN_NAMESPACE_STD
1746035553Spatrick 
1846035553Spatrick class _LIBCPP_HIDDEN __future_error_category
1946035553Spatrick     : public __do_message
2046035553Spatrick {
2146035553Spatrick public:
2276d0caaeSpatrick     virtual const char* name() const noexcept;
2346035553Spatrick     virtual string message(int ev) const;
2446035553Spatrick };
2546035553Spatrick 
2646035553Spatrick const char*
name() const2776d0caaeSpatrick __future_error_category::name() const noexcept
2846035553Spatrick {
2946035553Spatrick     return "future";
3046035553Spatrick }
3146035553Spatrick 
32*4bdff4beSrobert _LIBCPP_DIAGNOSTIC_PUSH
33*4bdff4beSrobert _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")
34*4bdff4beSrobert _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")
3546035553Spatrick 
3646035553Spatrick string
message(int ev) const3746035553Spatrick __future_error_category::message(int ev) const
3846035553Spatrick {
3946035553Spatrick     switch (static_cast<future_errc>(ev))
4046035553Spatrick     {
4146035553Spatrick     case future_errc(0):  // For backwards compatibility with C++11 (LWG 2056)
4246035553Spatrick     case future_errc::broken_promise:
4346035553Spatrick         return string("The associated promise has been destructed prior "
4446035553Spatrick                       "to the associated state becoming ready.");
4546035553Spatrick     case future_errc::future_already_retrieved:
4646035553Spatrick         return string("The future has already been retrieved from "
4746035553Spatrick                       "the promise or packaged_task.");
4846035553Spatrick     case future_errc::promise_already_satisfied:
4946035553Spatrick         return string("The state of the promise has already been set.");
5046035553Spatrick     case future_errc::no_state:
5146035553Spatrick         return string("Operation not permitted on an object without "
5246035553Spatrick                       "an associated state.");
5346035553Spatrick     }
5446035553Spatrick     return string("unspecified future_errc value\n");
5546035553Spatrick }
5646035553Spatrick 
57*4bdff4beSrobert _LIBCPP_DIAGNOSTIC_POP
5846035553Spatrick 
5946035553Spatrick const error_category&
future_category()6076d0caaeSpatrick future_category() noexcept
6146035553Spatrick {
6246035553Spatrick     static __future_error_category __f;
6346035553Spatrick     return __f;
6446035553Spatrick }
6546035553Spatrick 
future_error(error_code __ec)6646035553Spatrick future_error::future_error(error_code __ec)
6746035553Spatrick     : logic_error(__ec.message()),
6846035553Spatrick       __ec_(__ec)
6946035553Spatrick {
7046035553Spatrick }
7146035553Spatrick 
~future_error()7276d0caaeSpatrick future_error::~future_error() noexcept
7346035553Spatrick {
7446035553Spatrick }
7546035553Spatrick 
7646035553Spatrick void
__on_zero_shared()7776d0caaeSpatrick __assoc_sub_state::__on_zero_shared() noexcept
7846035553Spatrick {
7946035553Spatrick     delete this;
8046035553Spatrick }
8146035553Spatrick 
8246035553Spatrick void
set_value()8346035553Spatrick __assoc_sub_state::set_value()
8446035553Spatrick {
8546035553Spatrick     unique_lock<mutex> __lk(__mut_);
8646035553Spatrick     if (__has_value())
8746035553Spatrick         __throw_future_error(future_errc::promise_already_satisfied);
8846035553Spatrick     __state_ |= __constructed | ready;
8946035553Spatrick     __cv_.notify_all();
9046035553Spatrick }
9146035553Spatrick 
9246035553Spatrick void
set_value_at_thread_exit()9346035553Spatrick __assoc_sub_state::set_value_at_thread_exit()
9446035553Spatrick {
9546035553Spatrick     unique_lock<mutex> __lk(__mut_);
9646035553Spatrick     if (__has_value())
9746035553Spatrick         __throw_future_error(future_errc::promise_already_satisfied);
9846035553Spatrick     __state_ |= __constructed;
9946035553Spatrick     __thread_local_data()->__make_ready_at_thread_exit(this);
10046035553Spatrick }
10146035553Spatrick 
10246035553Spatrick void
set_exception(exception_ptr __p)10346035553Spatrick __assoc_sub_state::set_exception(exception_ptr __p)
10446035553Spatrick {
10546035553Spatrick     unique_lock<mutex> __lk(__mut_);
10646035553Spatrick     if (__has_value())
10746035553Spatrick         __throw_future_error(future_errc::promise_already_satisfied);
10846035553Spatrick     __exception_ = __p;
10946035553Spatrick     __state_ |= ready;
11046035553Spatrick     __cv_.notify_all();
11146035553Spatrick }
11246035553Spatrick 
11346035553Spatrick void
set_exception_at_thread_exit(exception_ptr __p)11446035553Spatrick __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
11546035553Spatrick {
11646035553Spatrick     unique_lock<mutex> __lk(__mut_);
11746035553Spatrick     if (__has_value())
11846035553Spatrick         __throw_future_error(future_errc::promise_already_satisfied);
11946035553Spatrick     __exception_ = __p;
12046035553Spatrick     __thread_local_data()->__make_ready_at_thread_exit(this);
12146035553Spatrick }
12246035553Spatrick 
12346035553Spatrick void
__make_ready()12446035553Spatrick __assoc_sub_state::__make_ready()
12546035553Spatrick {
12646035553Spatrick     unique_lock<mutex> __lk(__mut_);
12746035553Spatrick     __state_ |= ready;
12846035553Spatrick     __cv_.notify_all();
12946035553Spatrick }
13046035553Spatrick 
13146035553Spatrick void
copy()13246035553Spatrick __assoc_sub_state::copy()
13346035553Spatrick {
13446035553Spatrick     unique_lock<mutex> __lk(__mut_);
13546035553Spatrick     __sub_wait(__lk);
13646035553Spatrick     if (__exception_ != nullptr)
13746035553Spatrick         rethrow_exception(__exception_);
13846035553Spatrick }
13946035553Spatrick 
14046035553Spatrick void
wait()14146035553Spatrick __assoc_sub_state::wait()
14246035553Spatrick {
14346035553Spatrick     unique_lock<mutex> __lk(__mut_);
14446035553Spatrick     __sub_wait(__lk);
14546035553Spatrick }
14646035553Spatrick 
14746035553Spatrick void
__sub_wait(unique_lock<mutex> & __lk)14846035553Spatrick __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
14946035553Spatrick {
15046035553Spatrick     if (!__is_ready())
15146035553Spatrick     {
15246035553Spatrick         if (__state_ & static_cast<unsigned>(deferred))
15346035553Spatrick         {
15446035553Spatrick             __state_ &= ~static_cast<unsigned>(deferred);
15546035553Spatrick             __lk.unlock();
15646035553Spatrick             __execute();
15746035553Spatrick         }
15846035553Spatrick         else
15946035553Spatrick             while (!__is_ready())
16046035553Spatrick                 __cv_.wait(__lk);
16146035553Spatrick     }
16246035553Spatrick }
16346035553Spatrick 
16446035553Spatrick void
__execute()16546035553Spatrick __assoc_sub_state::__execute()
16646035553Spatrick {
16746035553Spatrick     __throw_future_error(future_errc::no_state);
16846035553Spatrick }
16946035553Spatrick 
future(__assoc_sub_state * __state)17046035553Spatrick future<void>::future(__assoc_sub_state* __state)
17146035553Spatrick     : __state_(__state)
17246035553Spatrick {
17346035553Spatrick     __state_->__attach_future();
17446035553Spatrick }
17546035553Spatrick 
~future()17646035553Spatrick future<void>::~future()
17746035553Spatrick {
17846035553Spatrick     if (__state_)
17946035553Spatrick         __state_->__release_shared();
18046035553Spatrick }
18146035553Spatrick 
18246035553Spatrick void
get()18346035553Spatrick future<void>::get()
18446035553Spatrick {
18546035553Spatrick     unique_ptr<__shared_count, __release_shared_count> __(__state_);
18646035553Spatrick     __assoc_sub_state* __s = __state_;
18746035553Spatrick     __state_ = nullptr;
18846035553Spatrick     __s->copy();
18946035553Spatrick }
19046035553Spatrick 
promise()19146035553Spatrick promise<void>::promise()
19246035553Spatrick     : __state_(new __assoc_sub_state)
19346035553Spatrick {
19446035553Spatrick }
19546035553Spatrick 
~promise()19646035553Spatrick promise<void>::~promise()
19746035553Spatrick {
19846035553Spatrick     if (__state_)
19946035553Spatrick     {
20046035553Spatrick #ifndef _LIBCPP_NO_EXCEPTIONS
20146035553Spatrick         if (!__state_->__has_value() && __state_->use_count() > 1)
20246035553Spatrick             __state_->set_exception(make_exception_ptr(
20346035553Spatrick                       future_error(make_error_code(future_errc::broken_promise))
20446035553Spatrick                                                       ));
20546035553Spatrick #endif // _LIBCPP_NO_EXCEPTIONS
20646035553Spatrick         __state_->__release_shared();
20746035553Spatrick     }
20846035553Spatrick }
20946035553Spatrick 
21046035553Spatrick future<void>
get_future()21146035553Spatrick promise<void>::get_future()
21246035553Spatrick {
21346035553Spatrick     if (__state_ == nullptr)
21446035553Spatrick         __throw_future_error(future_errc::no_state);
21546035553Spatrick     return future<void>(__state_);
21646035553Spatrick }
21746035553Spatrick 
21846035553Spatrick void
set_value()21946035553Spatrick promise<void>::set_value()
22046035553Spatrick {
22146035553Spatrick     if (__state_ == nullptr)
22246035553Spatrick         __throw_future_error(future_errc::no_state);
22346035553Spatrick     __state_->set_value();
22446035553Spatrick }
22546035553Spatrick 
22646035553Spatrick void
set_exception(exception_ptr __p)22746035553Spatrick promise<void>::set_exception(exception_ptr __p)
22846035553Spatrick {
22946035553Spatrick     if (__state_ == nullptr)
23046035553Spatrick         __throw_future_error(future_errc::no_state);
23146035553Spatrick     __state_->set_exception(__p);
23246035553Spatrick }
23346035553Spatrick 
23446035553Spatrick void
set_value_at_thread_exit()23546035553Spatrick promise<void>::set_value_at_thread_exit()
23646035553Spatrick {
23746035553Spatrick     if (__state_ == nullptr)
23846035553Spatrick         __throw_future_error(future_errc::no_state);
23946035553Spatrick     __state_->set_value_at_thread_exit();
24046035553Spatrick }
24146035553Spatrick 
24246035553Spatrick void
set_exception_at_thread_exit(exception_ptr __p)24346035553Spatrick promise<void>::set_exception_at_thread_exit(exception_ptr __p)
24446035553Spatrick {
24546035553Spatrick     if (__state_ == nullptr)
24646035553Spatrick         __throw_future_error(future_errc::no_state);
24746035553Spatrick     __state_->set_exception_at_thread_exit(__p);
24846035553Spatrick }
24946035553Spatrick 
~shared_future()25046035553Spatrick shared_future<void>::~shared_future()
25146035553Spatrick {
25246035553Spatrick     if (__state_)
25346035553Spatrick         __state_->__release_shared();
25446035553Spatrick }
25546035553Spatrick 
25646035553Spatrick shared_future<void>&
operator =(const shared_future & __rhs)25746035553Spatrick shared_future<void>::operator=(const shared_future& __rhs)
25846035553Spatrick {
25946035553Spatrick     if (__rhs.__state_)
26046035553Spatrick         __rhs.__state_->__add_shared();
26146035553Spatrick     if (__state_)
26246035553Spatrick         __state_->__release_shared();
26346035553Spatrick     __state_ = __rhs.__state_;
26446035553Spatrick     return *this;
26546035553Spatrick }
26646035553Spatrick 
26746035553Spatrick _LIBCPP_END_NAMESPACE_STD
26846035553Spatrick 
26946035553Spatrick #endif // !_LIBCPP_HAS_NO_THREADS
270