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