xref: /freebsd/contrib/llvm-project/libcxx/src/future.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===------------------------- future.cpp ---------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "__config"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "future"
140b57cec5SDimitry Andric #include "string"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric class _LIBCPP_HIDDEN __future_error_category
190b57cec5SDimitry Andric     : public __do_message
200b57cec5SDimitry Andric {
210b57cec5SDimitry Andric public:
22*fe6060f1SDimitry Andric     virtual const char* name() const noexcept;
230b57cec5SDimitry Andric     virtual string message(int ev) const;
240b57cec5SDimitry Andric };
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric const char*
27*fe6060f1SDimitry Andric __future_error_category::name() const noexcept
280b57cec5SDimitry Andric {
290b57cec5SDimitry Andric     return "future";
300b57cec5SDimitry Andric }
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric #if defined(__clang__)
330b57cec5SDimitry Andric #pragma clang diagnostic push
340b57cec5SDimitry Andric #pragma clang diagnostic ignored "-Wswitch"
350b57cec5SDimitry Andric #elif defined(__GNUC__) || defined(__GNUG__)
360b57cec5SDimitry Andric #pragma GCC diagnostic push
370b57cec5SDimitry Andric #pragma GCC diagnostic ignored "-Wswitch"
380b57cec5SDimitry Andric #endif
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric string
410b57cec5SDimitry Andric __future_error_category::message(int ev) const
420b57cec5SDimitry Andric {
430b57cec5SDimitry Andric     switch (static_cast<future_errc>(ev))
440b57cec5SDimitry Andric     {
450b57cec5SDimitry Andric     case future_errc(0):  // For backwards compatibility with C++11 (LWG 2056)
460b57cec5SDimitry Andric     case future_errc::broken_promise:
470b57cec5SDimitry Andric         return string("The associated promise has been destructed prior "
480b57cec5SDimitry Andric                       "to the associated state becoming ready.");
490b57cec5SDimitry Andric     case future_errc::future_already_retrieved:
500b57cec5SDimitry Andric         return string("The future has already been retrieved from "
510b57cec5SDimitry Andric                       "the promise or packaged_task.");
520b57cec5SDimitry Andric     case future_errc::promise_already_satisfied:
530b57cec5SDimitry Andric         return string("The state of the promise has already been set.");
540b57cec5SDimitry Andric     case future_errc::no_state:
550b57cec5SDimitry Andric         return string("Operation not permitted on an object without "
560b57cec5SDimitry Andric                       "an associated state.");
570b57cec5SDimitry Andric     }
580b57cec5SDimitry Andric     return string("unspecified future_errc value\n");
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric #if defined(__clang__)
620b57cec5SDimitry Andric #pragma clang diagnostic pop
630b57cec5SDimitry Andric #elif defined(__GNUC__) || defined(__GNUG__)
640b57cec5SDimitry Andric #pragma GCC diagnostic pop
650b57cec5SDimitry Andric #endif
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric const error_category&
68*fe6060f1SDimitry Andric future_category() noexcept
690b57cec5SDimitry Andric {
700b57cec5SDimitry Andric     static __future_error_category __f;
710b57cec5SDimitry Andric     return __f;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric future_error::future_error(error_code __ec)
750b57cec5SDimitry Andric     : logic_error(__ec.message()),
760b57cec5SDimitry Andric       __ec_(__ec)
770b57cec5SDimitry Andric {
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric 
80*fe6060f1SDimitry Andric future_error::~future_error() noexcept
810b57cec5SDimitry Andric {
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric void
85*fe6060f1SDimitry Andric __assoc_sub_state::__on_zero_shared() noexcept
860b57cec5SDimitry Andric {
870b57cec5SDimitry Andric     delete this;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric void
910b57cec5SDimitry Andric __assoc_sub_state::set_value()
920b57cec5SDimitry Andric {
930b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
940b57cec5SDimitry Andric     if (__has_value())
950b57cec5SDimitry Andric         __throw_future_error(future_errc::promise_already_satisfied);
960b57cec5SDimitry Andric     __state_ |= __constructed | ready;
970b57cec5SDimitry Andric     __cv_.notify_all();
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric void
1010b57cec5SDimitry Andric __assoc_sub_state::set_value_at_thread_exit()
1020b57cec5SDimitry Andric {
1030b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1040b57cec5SDimitry Andric     if (__has_value())
1050b57cec5SDimitry Andric         __throw_future_error(future_errc::promise_already_satisfied);
1060b57cec5SDimitry Andric     __state_ |= __constructed;
1070b57cec5SDimitry Andric     __thread_local_data()->__make_ready_at_thread_exit(this);
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric void
1110b57cec5SDimitry Andric __assoc_sub_state::set_exception(exception_ptr __p)
1120b57cec5SDimitry Andric {
1130b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1140b57cec5SDimitry Andric     if (__has_value())
1150b57cec5SDimitry Andric         __throw_future_error(future_errc::promise_already_satisfied);
1160b57cec5SDimitry Andric     __exception_ = __p;
1170b57cec5SDimitry Andric     __state_ |= ready;
1180b57cec5SDimitry Andric     __cv_.notify_all();
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric void
1220b57cec5SDimitry Andric __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
1230b57cec5SDimitry Andric {
1240b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1250b57cec5SDimitry Andric     if (__has_value())
1260b57cec5SDimitry Andric         __throw_future_error(future_errc::promise_already_satisfied);
1270b57cec5SDimitry Andric     __exception_ = __p;
1280b57cec5SDimitry Andric     __thread_local_data()->__make_ready_at_thread_exit(this);
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric void
1320b57cec5SDimitry Andric __assoc_sub_state::__make_ready()
1330b57cec5SDimitry Andric {
1340b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1350b57cec5SDimitry Andric     __state_ |= ready;
1360b57cec5SDimitry Andric     __cv_.notify_all();
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric void
1400b57cec5SDimitry Andric __assoc_sub_state::copy()
1410b57cec5SDimitry Andric {
1420b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1430b57cec5SDimitry Andric     __sub_wait(__lk);
1440b57cec5SDimitry Andric     if (__exception_ != nullptr)
1450b57cec5SDimitry Andric         rethrow_exception(__exception_);
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric void
1490b57cec5SDimitry Andric __assoc_sub_state::wait()
1500b57cec5SDimitry Andric {
1510b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1520b57cec5SDimitry Andric     __sub_wait(__lk);
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric void
1560b57cec5SDimitry Andric __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
1570b57cec5SDimitry Andric {
1580b57cec5SDimitry Andric     if (!__is_ready())
1590b57cec5SDimitry Andric     {
1600b57cec5SDimitry Andric         if (__state_ & static_cast<unsigned>(deferred))
1610b57cec5SDimitry Andric         {
1620b57cec5SDimitry Andric             __state_ &= ~static_cast<unsigned>(deferred);
1630b57cec5SDimitry Andric             __lk.unlock();
1640b57cec5SDimitry Andric             __execute();
1650b57cec5SDimitry Andric         }
1660b57cec5SDimitry Andric         else
1670b57cec5SDimitry Andric             while (!__is_ready())
1680b57cec5SDimitry Andric                 __cv_.wait(__lk);
1690b57cec5SDimitry Andric     }
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric void
1730b57cec5SDimitry Andric __assoc_sub_state::__execute()
1740b57cec5SDimitry Andric {
1750b57cec5SDimitry Andric     __throw_future_error(future_errc::no_state);
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric future<void>::future(__assoc_sub_state* __state)
1790b57cec5SDimitry Andric     : __state_(__state)
1800b57cec5SDimitry Andric {
1810b57cec5SDimitry Andric     __state_->__attach_future();
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric future<void>::~future()
1850b57cec5SDimitry Andric {
1860b57cec5SDimitry Andric     if (__state_)
1870b57cec5SDimitry Andric         __state_->__release_shared();
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric void
1910b57cec5SDimitry Andric future<void>::get()
1920b57cec5SDimitry Andric {
1930b57cec5SDimitry Andric     unique_ptr<__shared_count, __release_shared_count> __(__state_);
1940b57cec5SDimitry Andric     __assoc_sub_state* __s = __state_;
1950b57cec5SDimitry Andric     __state_ = nullptr;
1960b57cec5SDimitry Andric     __s->copy();
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric promise<void>::promise()
2000b57cec5SDimitry Andric     : __state_(new __assoc_sub_state)
2010b57cec5SDimitry Andric {
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric promise<void>::~promise()
2050b57cec5SDimitry Andric {
2060b57cec5SDimitry Andric     if (__state_)
2070b57cec5SDimitry Andric     {
2080b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
2090b57cec5SDimitry Andric         if (!__state_->__has_value() && __state_->use_count() > 1)
2100b57cec5SDimitry Andric             __state_->set_exception(make_exception_ptr(
2110b57cec5SDimitry Andric                       future_error(make_error_code(future_errc::broken_promise))
2120b57cec5SDimitry Andric                                                       ));
2130b57cec5SDimitry Andric #endif // _LIBCPP_NO_EXCEPTIONS
2140b57cec5SDimitry Andric         __state_->__release_shared();
2150b57cec5SDimitry Andric     }
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric future<void>
2190b57cec5SDimitry Andric promise<void>::get_future()
2200b57cec5SDimitry Andric {
2210b57cec5SDimitry Andric     if (__state_ == nullptr)
2220b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2230b57cec5SDimitry Andric     return future<void>(__state_);
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric void
2270b57cec5SDimitry Andric promise<void>::set_value()
2280b57cec5SDimitry Andric {
2290b57cec5SDimitry Andric     if (__state_ == nullptr)
2300b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2310b57cec5SDimitry Andric     __state_->set_value();
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric void
2350b57cec5SDimitry Andric promise<void>::set_exception(exception_ptr __p)
2360b57cec5SDimitry Andric {
2370b57cec5SDimitry Andric     if (__state_ == nullptr)
2380b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2390b57cec5SDimitry Andric     __state_->set_exception(__p);
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric void
2430b57cec5SDimitry Andric promise<void>::set_value_at_thread_exit()
2440b57cec5SDimitry Andric {
2450b57cec5SDimitry Andric     if (__state_ == nullptr)
2460b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2470b57cec5SDimitry Andric     __state_->set_value_at_thread_exit();
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric void
2510b57cec5SDimitry Andric promise<void>::set_exception_at_thread_exit(exception_ptr __p)
2520b57cec5SDimitry Andric {
2530b57cec5SDimitry Andric     if (__state_ == nullptr)
2540b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2550b57cec5SDimitry Andric     __state_->set_exception_at_thread_exit(__p);
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric shared_future<void>::~shared_future()
2590b57cec5SDimitry Andric {
2600b57cec5SDimitry Andric     if (__state_)
2610b57cec5SDimitry Andric         __state_->__release_shared();
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric shared_future<void>&
2650b57cec5SDimitry Andric shared_future<void>::operator=(const shared_future& __rhs)
2660b57cec5SDimitry Andric {
2670b57cec5SDimitry Andric     if (__rhs.__state_)
2680b57cec5SDimitry Andric         __rhs.__state_->__add_shared();
2690b57cec5SDimitry Andric     if (__state_)
2700b57cec5SDimitry Andric         __state_->__release_shared();
2710b57cec5SDimitry Andric     __state_ = __rhs.__state_;
2720b57cec5SDimitry Andric     return *this;
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric #endif // !_LIBCPP_HAS_NO_THREADS
278