xref: /freebsd/contrib/llvm-project/libcxx/src/future.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
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 
981ad6265SDimitry Andric #include <future>
1081ad6265SDimitry Andric #include <string>
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric class _LIBCPP_HIDDEN __future_error_category
150b57cec5SDimitry Andric     : public __do_message
160b57cec5SDimitry Andric {
170b57cec5SDimitry Andric public:
18fe6060f1SDimitry Andric     virtual const char* name() const noexcept;
190b57cec5SDimitry Andric     virtual string message(int ev) const;
200b57cec5SDimitry Andric };
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric const char*
23fe6060f1SDimitry Andric __future_error_category::name() const noexcept
240b57cec5SDimitry Andric {
250b57cec5SDimitry Andric     return "future";
260b57cec5SDimitry Andric }
270b57cec5SDimitry Andric 
2881ad6265SDimitry Andric _LIBCPP_DIAGNOSTIC_PUSH
2981ad6265SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")
3081ad6265SDimitry Andric _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric string
330b57cec5SDimitry Andric __future_error_category::message(int ev) const
340b57cec5SDimitry Andric {
350b57cec5SDimitry Andric     switch (static_cast<future_errc>(ev))
360b57cec5SDimitry Andric     {
370b57cec5SDimitry Andric     case future_errc(0):  // For backwards compatibility with C++11 (LWG 2056)
380b57cec5SDimitry Andric     case future_errc::broken_promise:
390b57cec5SDimitry Andric         return string("The associated promise has been destructed prior "
400b57cec5SDimitry Andric                       "to the associated state becoming ready.");
410b57cec5SDimitry Andric     case future_errc::future_already_retrieved:
420b57cec5SDimitry Andric         return string("The future has already been retrieved from "
430b57cec5SDimitry Andric                       "the promise or packaged_task.");
440b57cec5SDimitry Andric     case future_errc::promise_already_satisfied:
450b57cec5SDimitry Andric         return string("The state of the promise has already been set.");
460b57cec5SDimitry Andric     case future_errc::no_state:
470b57cec5SDimitry Andric         return string("Operation not permitted on an object without "
480b57cec5SDimitry Andric                       "an associated state.");
490b57cec5SDimitry Andric     }
500b57cec5SDimitry Andric     return string("unspecified future_errc value\n");
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
5381ad6265SDimitry Andric _LIBCPP_DIAGNOSTIC_POP
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric const error_category&
56fe6060f1SDimitry Andric future_category() noexcept
570b57cec5SDimitry Andric {
58*5f757f3fSDimitry Andric     union AvoidDestroyingFutureCategory {
59*5f757f3fSDimitry Andric         __future_error_category future_error_category;
60*5f757f3fSDimitry Andric         constexpr explicit AvoidDestroyingFutureCategory() : future_error_category() {}
61*5f757f3fSDimitry Andric         ~AvoidDestroyingFutureCategory() {}
62*5f757f3fSDimitry Andric     };
63*5f757f3fSDimitry Andric     constinit static AvoidDestroyingFutureCategory helper;
64*5f757f3fSDimitry Andric     return helper.future_error_category;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric future_error::future_error(error_code __ec)
680b57cec5SDimitry Andric     : logic_error(__ec.message()),
690b57cec5SDimitry Andric       __ec_(__ec)
700b57cec5SDimitry Andric {
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
73fe6060f1SDimitry Andric future_error::~future_error() noexcept
740b57cec5SDimitry Andric {
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric void
78fe6060f1SDimitry Andric __assoc_sub_state::__on_zero_shared() noexcept
790b57cec5SDimitry Andric {
800b57cec5SDimitry Andric     delete this;
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric void
840b57cec5SDimitry Andric __assoc_sub_state::set_value()
850b57cec5SDimitry Andric {
860b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
870b57cec5SDimitry Andric     if (__has_value())
880b57cec5SDimitry Andric         __throw_future_error(future_errc::promise_already_satisfied);
890b57cec5SDimitry Andric     __state_ |= __constructed | ready;
900b57cec5SDimitry Andric     __cv_.notify_all();
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric void
940b57cec5SDimitry Andric __assoc_sub_state::set_value_at_thread_exit()
950b57cec5SDimitry Andric {
960b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
970b57cec5SDimitry Andric     if (__has_value())
980b57cec5SDimitry Andric         __throw_future_error(future_errc::promise_already_satisfied);
990b57cec5SDimitry Andric     __state_ |= __constructed;
1000b57cec5SDimitry Andric     __thread_local_data()->__make_ready_at_thread_exit(this);
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric void
1040b57cec5SDimitry Andric __assoc_sub_state::set_exception(exception_ptr __p)
1050b57cec5SDimitry Andric {
1060b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1070b57cec5SDimitry Andric     if (__has_value())
1080b57cec5SDimitry Andric         __throw_future_error(future_errc::promise_already_satisfied);
1090b57cec5SDimitry Andric     __exception_ = __p;
1100b57cec5SDimitry Andric     __state_ |= ready;
1110b57cec5SDimitry Andric     __cv_.notify_all();
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric void
1150b57cec5SDimitry Andric __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
1160b57cec5SDimitry Andric {
1170b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1180b57cec5SDimitry Andric     if (__has_value())
1190b57cec5SDimitry Andric         __throw_future_error(future_errc::promise_already_satisfied);
1200b57cec5SDimitry Andric     __exception_ = __p;
1210b57cec5SDimitry Andric     __thread_local_data()->__make_ready_at_thread_exit(this);
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric void
1250b57cec5SDimitry Andric __assoc_sub_state::__make_ready()
1260b57cec5SDimitry Andric {
1270b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1280b57cec5SDimitry Andric     __state_ |= ready;
1290b57cec5SDimitry Andric     __cv_.notify_all();
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric void
1330b57cec5SDimitry Andric __assoc_sub_state::copy()
1340b57cec5SDimitry Andric {
1350b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1360b57cec5SDimitry Andric     __sub_wait(__lk);
1370b57cec5SDimitry Andric     if (__exception_ != nullptr)
1380b57cec5SDimitry Andric         rethrow_exception(__exception_);
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric void
1420b57cec5SDimitry Andric __assoc_sub_state::wait()
1430b57cec5SDimitry Andric {
1440b57cec5SDimitry Andric     unique_lock<mutex> __lk(__mut_);
1450b57cec5SDimitry Andric     __sub_wait(__lk);
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric void
1490b57cec5SDimitry Andric __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
1500b57cec5SDimitry Andric {
1510b57cec5SDimitry Andric     if (!__is_ready())
1520b57cec5SDimitry Andric     {
1530b57cec5SDimitry Andric         if (__state_ & static_cast<unsigned>(deferred))
1540b57cec5SDimitry Andric         {
1550b57cec5SDimitry Andric             __state_ &= ~static_cast<unsigned>(deferred);
1560b57cec5SDimitry Andric             __lk.unlock();
1570b57cec5SDimitry Andric             __execute();
1580b57cec5SDimitry Andric         }
1590b57cec5SDimitry Andric         else
1600b57cec5SDimitry Andric             while (!__is_ready())
1610b57cec5SDimitry Andric                 __cv_.wait(__lk);
1620b57cec5SDimitry Andric     }
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric void
1660b57cec5SDimitry Andric __assoc_sub_state::__execute()
1670b57cec5SDimitry Andric {
1680b57cec5SDimitry Andric     __throw_future_error(future_errc::no_state);
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric future<void>::future(__assoc_sub_state* __state)
1720b57cec5SDimitry Andric     : __state_(__state)
1730b57cec5SDimitry Andric {
1740b57cec5SDimitry Andric     __state_->__attach_future();
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric future<void>::~future()
1780b57cec5SDimitry Andric {
1790b57cec5SDimitry Andric     if (__state_)
1800b57cec5SDimitry Andric         __state_->__release_shared();
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric void
1840b57cec5SDimitry Andric future<void>::get()
1850b57cec5SDimitry Andric {
1860b57cec5SDimitry Andric     unique_ptr<__shared_count, __release_shared_count> __(__state_);
1870b57cec5SDimitry Andric     __assoc_sub_state* __s = __state_;
1880b57cec5SDimitry Andric     __state_ = nullptr;
1890b57cec5SDimitry Andric     __s->copy();
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric promise<void>::promise()
1930b57cec5SDimitry Andric     : __state_(new __assoc_sub_state)
1940b57cec5SDimitry Andric {
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric promise<void>::~promise()
1980b57cec5SDimitry Andric {
1990b57cec5SDimitry Andric     if (__state_)
2000b57cec5SDimitry Andric     {
20106c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
2020b57cec5SDimitry Andric         if (!__state_->__has_value() && __state_->use_count() > 1)
203*5f757f3fSDimitry Andric             __state_->set_exception(make_exception_ptr(future_error(future_errc::broken_promise)));
20406c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS
2050b57cec5SDimitry Andric         __state_->__release_shared();
2060b57cec5SDimitry Andric     }
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric future<void>
2100b57cec5SDimitry Andric promise<void>::get_future()
2110b57cec5SDimitry Andric {
2120b57cec5SDimitry Andric     if (__state_ == nullptr)
2130b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2140b57cec5SDimitry Andric     return future<void>(__state_);
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric void
2180b57cec5SDimitry Andric promise<void>::set_value()
2190b57cec5SDimitry Andric {
2200b57cec5SDimitry Andric     if (__state_ == nullptr)
2210b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2220b57cec5SDimitry Andric     __state_->set_value();
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric void
2260b57cec5SDimitry Andric promise<void>::set_exception(exception_ptr __p)
2270b57cec5SDimitry Andric {
2280b57cec5SDimitry Andric     if (__state_ == nullptr)
2290b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2300b57cec5SDimitry Andric     __state_->set_exception(__p);
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric void
2340b57cec5SDimitry Andric promise<void>::set_value_at_thread_exit()
2350b57cec5SDimitry Andric {
2360b57cec5SDimitry Andric     if (__state_ == nullptr)
2370b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2380b57cec5SDimitry Andric     __state_->set_value_at_thread_exit();
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric void
2420b57cec5SDimitry Andric promise<void>::set_exception_at_thread_exit(exception_ptr __p)
2430b57cec5SDimitry Andric {
2440b57cec5SDimitry Andric     if (__state_ == nullptr)
2450b57cec5SDimitry Andric         __throw_future_error(future_errc::no_state);
2460b57cec5SDimitry Andric     __state_->set_exception_at_thread_exit(__p);
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric shared_future<void>::~shared_future()
2500b57cec5SDimitry Andric {
2510b57cec5SDimitry Andric     if (__state_)
2520b57cec5SDimitry Andric         __state_->__release_shared();
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric shared_future<void>&
2560b57cec5SDimitry Andric shared_future<void>::operator=(const shared_future& __rhs)
2570b57cec5SDimitry Andric {
2580b57cec5SDimitry Andric     if (__rhs.__state_)
2590b57cec5SDimitry Andric         __rhs.__state_->__add_shared();
2600b57cec5SDimitry Andric     if (__state_)
2610b57cec5SDimitry Andric         __state_->__release_shared();
2620b57cec5SDimitry Andric     __state_ = __rhs.__state_;
2630b57cec5SDimitry Andric     return *this;
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
267