xref: /minix3/external/bsd/libc++/dist/libcxx/src/future.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
14684ddb6SLionel Sambuc //===------------------------- future.cpp ---------------------------------===//
24684ddb6SLionel Sambuc //
34684ddb6SLionel Sambuc //                     The LLVM Compiler Infrastructure
44684ddb6SLionel Sambuc //
54684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
64684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
74684ddb6SLionel Sambuc //
84684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
94684ddb6SLionel Sambuc 
10*0a6a1f1dSLionel Sambuc #include "__config"
11*0a6a1f1dSLionel Sambuc 
12*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
13*0a6a1f1dSLionel Sambuc 
144684ddb6SLionel Sambuc #include "future"
154684ddb6SLionel Sambuc #include "string"
164684ddb6SLionel Sambuc 
174684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD
184684ddb6SLionel Sambuc 
194684ddb6SLionel Sambuc class _LIBCPP_HIDDEN __future_error_category
204684ddb6SLionel Sambuc     : public __do_message
214684ddb6SLionel Sambuc {
224684ddb6SLionel Sambuc public:
234684ddb6SLionel Sambuc     virtual const char* name() const _NOEXCEPT;
244684ddb6SLionel Sambuc     virtual string message(int ev) const;
254684ddb6SLionel Sambuc };
264684ddb6SLionel Sambuc 
274684ddb6SLionel Sambuc const char*
name() const284684ddb6SLionel Sambuc __future_error_category::name() const _NOEXCEPT
294684ddb6SLionel Sambuc {
304684ddb6SLionel Sambuc     return "future";
314684ddb6SLionel Sambuc }
324684ddb6SLionel Sambuc 
33*0a6a1f1dSLionel Sambuc #if defined(__clang__)
344684ddb6SLionel Sambuc #pragma clang diagnostic push
354684ddb6SLionel Sambuc #pragma clang diagnostic ignored "-Wswitch"
36*0a6a1f1dSLionel Sambuc #elif defined(__GNUC__) || defined(__GNUG__)
37*0a6a1f1dSLionel Sambuc #pragma GCC diagnostic push
38*0a6a1f1dSLionel Sambuc #pragma GCC diagnostic ignored "-Wswitch"
39*0a6a1f1dSLionel Sambuc #endif
404684ddb6SLionel Sambuc 
414684ddb6SLionel Sambuc string
message(int ev) const424684ddb6SLionel Sambuc __future_error_category::message(int ev) const
434684ddb6SLionel Sambuc {
444684ddb6SLionel Sambuc     switch (static_cast<future_errc>(ev))
454684ddb6SLionel Sambuc     {
464684ddb6SLionel Sambuc     case future_errc(0):  // For backwards compatibility with C++11 (LWG 2056)
474684ddb6SLionel Sambuc     case future_errc::broken_promise:
484684ddb6SLionel Sambuc         return string("The associated promise has been destructed prior "
494684ddb6SLionel Sambuc                       "to the associated state becoming ready.");
504684ddb6SLionel Sambuc     case future_errc::future_already_retrieved:
514684ddb6SLionel Sambuc         return string("The future has already been retrieved from "
524684ddb6SLionel Sambuc                       "the promise or packaged_task.");
534684ddb6SLionel Sambuc     case future_errc::promise_already_satisfied:
544684ddb6SLionel Sambuc         return string("The state of the promise has already been set.");
554684ddb6SLionel Sambuc     case future_errc::no_state:
564684ddb6SLionel Sambuc         return string("Operation not permitted on an object without "
574684ddb6SLionel Sambuc                       "an associated state.");
584684ddb6SLionel Sambuc     }
594684ddb6SLionel Sambuc     return string("unspecified future_errc value\n");
604684ddb6SLionel Sambuc }
614684ddb6SLionel Sambuc 
62*0a6a1f1dSLionel Sambuc #if defined(__clang__)
634684ddb6SLionel Sambuc #pragma clang diagnostic pop
64*0a6a1f1dSLionel Sambuc #elif defined(__GNUC__) || defined(__GNUG__)
65*0a6a1f1dSLionel Sambuc #pragma GCC diagnostic pop
66*0a6a1f1dSLionel Sambuc #endif
674684ddb6SLionel Sambuc 
684684ddb6SLionel Sambuc const error_category&
future_category()694684ddb6SLionel Sambuc future_category() _NOEXCEPT
704684ddb6SLionel Sambuc {
714684ddb6SLionel Sambuc     static __future_error_category __f;
724684ddb6SLionel Sambuc     return __f;
734684ddb6SLionel Sambuc }
744684ddb6SLionel Sambuc 
future_error(error_code __ec)754684ddb6SLionel Sambuc future_error::future_error(error_code __ec)
764684ddb6SLionel Sambuc     : logic_error(__ec.message()),
774684ddb6SLionel Sambuc       __ec_(__ec)
784684ddb6SLionel Sambuc {
794684ddb6SLionel Sambuc }
804684ddb6SLionel Sambuc 
~future_error()814684ddb6SLionel Sambuc future_error::~future_error() _NOEXCEPT
824684ddb6SLionel Sambuc {
834684ddb6SLionel Sambuc }
844684ddb6SLionel Sambuc 
854684ddb6SLionel Sambuc void
__on_zero_shared()864684ddb6SLionel Sambuc __assoc_sub_state::__on_zero_shared() _NOEXCEPT
874684ddb6SLionel Sambuc {
884684ddb6SLionel Sambuc     delete this;
894684ddb6SLionel Sambuc }
904684ddb6SLionel Sambuc 
914684ddb6SLionel Sambuc void
set_value()924684ddb6SLionel Sambuc __assoc_sub_state::set_value()
934684ddb6SLionel Sambuc {
944684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
954684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
964684ddb6SLionel Sambuc     if (__has_value())
974684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::promise_already_satisfied));
984684ddb6SLionel Sambuc #endif
994684ddb6SLionel Sambuc     __state_ |= __constructed | ready;
1004684ddb6SLionel Sambuc     __cv_.notify_all();
1014684ddb6SLionel Sambuc }
1024684ddb6SLionel Sambuc 
1034684ddb6SLionel Sambuc void
set_value_at_thread_exit()1044684ddb6SLionel Sambuc __assoc_sub_state::set_value_at_thread_exit()
1054684ddb6SLionel Sambuc {
1064684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
1074684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
1084684ddb6SLionel Sambuc     if (__has_value())
1094684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::promise_already_satisfied));
1104684ddb6SLionel Sambuc #endif
1114684ddb6SLionel Sambuc     __state_ |= __constructed;
1124684ddb6SLionel Sambuc     __thread_local_data()->__make_ready_at_thread_exit(this);
1134684ddb6SLionel Sambuc }
1144684ddb6SLionel Sambuc 
1154684ddb6SLionel Sambuc void
set_exception(exception_ptr __p)1164684ddb6SLionel Sambuc __assoc_sub_state::set_exception(exception_ptr __p)
1174684ddb6SLionel Sambuc {
1184684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
1194684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
1204684ddb6SLionel Sambuc     if (__has_value())
1214684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::promise_already_satisfied));
1224684ddb6SLionel Sambuc #endif
1234684ddb6SLionel Sambuc     __exception_ = __p;
1244684ddb6SLionel Sambuc     __state_ |= ready;
1254684ddb6SLionel Sambuc     __cv_.notify_all();
1264684ddb6SLionel Sambuc }
1274684ddb6SLionel Sambuc 
1284684ddb6SLionel Sambuc void
set_exception_at_thread_exit(exception_ptr __p)1294684ddb6SLionel Sambuc __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
1304684ddb6SLionel Sambuc {
1314684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
1324684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
1334684ddb6SLionel Sambuc     if (__has_value())
1344684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::promise_already_satisfied));
1354684ddb6SLionel Sambuc #endif
1364684ddb6SLionel Sambuc     __exception_ = __p;
1374684ddb6SLionel Sambuc     __thread_local_data()->__make_ready_at_thread_exit(this);
1384684ddb6SLionel Sambuc }
1394684ddb6SLionel Sambuc 
1404684ddb6SLionel Sambuc void
__make_ready()1414684ddb6SLionel Sambuc __assoc_sub_state::__make_ready()
1424684ddb6SLionel Sambuc {
1434684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
1444684ddb6SLionel Sambuc     __state_ |= ready;
1454684ddb6SLionel Sambuc     __cv_.notify_all();
1464684ddb6SLionel Sambuc }
1474684ddb6SLionel Sambuc 
1484684ddb6SLionel Sambuc void
copy()1494684ddb6SLionel Sambuc __assoc_sub_state::copy()
1504684ddb6SLionel Sambuc {
1514684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
1524684ddb6SLionel Sambuc     __sub_wait(__lk);
1534684ddb6SLionel Sambuc     if (__exception_ != nullptr)
1544684ddb6SLionel Sambuc         rethrow_exception(__exception_);
1554684ddb6SLionel Sambuc }
1564684ddb6SLionel Sambuc 
1574684ddb6SLionel Sambuc void
wait()1584684ddb6SLionel Sambuc __assoc_sub_state::wait()
1594684ddb6SLionel Sambuc {
1604684ddb6SLionel Sambuc     unique_lock<mutex> __lk(__mut_);
1614684ddb6SLionel Sambuc     __sub_wait(__lk);
1624684ddb6SLionel Sambuc }
1634684ddb6SLionel Sambuc 
1644684ddb6SLionel Sambuc void
__sub_wait(unique_lock<mutex> & __lk)1654684ddb6SLionel Sambuc __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
1664684ddb6SLionel Sambuc {
1674684ddb6SLionel Sambuc     if (!__is_ready())
1684684ddb6SLionel Sambuc     {
1694684ddb6SLionel Sambuc         if (__state_ & static_cast<unsigned>(deferred))
1704684ddb6SLionel Sambuc         {
1714684ddb6SLionel Sambuc             __state_ &= ~static_cast<unsigned>(deferred);
1724684ddb6SLionel Sambuc             __lk.unlock();
1734684ddb6SLionel Sambuc             __execute();
1744684ddb6SLionel Sambuc         }
1754684ddb6SLionel Sambuc         else
1764684ddb6SLionel Sambuc             while (!__is_ready())
1774684ddb6SLionel Sambuc                 __cv_.wait(__lk);
1784684ddb6SLionel Sambuc     }
1794684ddb6SLionel Sambuc }
1804684ddb6SLionel Sambuc 
1814684ddb6SLionel Sambuc void
__execute()1824684ddb6SLionel Sambuc __assoc_sub_state::__execute()
1834684ddb6SLionel Sambuc {
1844684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
1854684ddb6SLionel Sambuc     throw future_error(make_error_code(future_errc::no_state));
1864684ddb6SLionel Sambuc #endif
1874684ddb6SLionel Sambuc }
1884684ddb6SLionel Sambuc 
future(__assoc_sub_state * __state)1894684ddb6SLionel Sambuc future<void>::future(__assoc_sub_state* __state)
1904684ddb6SLionel Sambuc     : __state_(__state)
1914684ddb6SLionel Sambuc {
1924684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
1934684ddb6SLionel Sambuc     if (__state_->__has_future_attached())
1944684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::future_already_retrieved));
1954684ddb6SLionel Sambuc #endif
1964684ddb6SLionel Sambuc     __state_->__add_shared();
1974684ddb6SLionel Sambuc     __state_->__set_future_attached();
1984684ddb6SLionel Sambuc }
1994684ddb6SLionel Sambuc 
~future()2004684ddb6SLionel Sambuc future<void>::~future()
2014684ddb6SLionel Sambuc {
2024684ddb6SLionel Sambuc     if (__state_)
2034684ddb6SLionel Sambuc         __state_->__release_shared();
2044684ddb6SLionel Sambuc }
2054684ddb6SLionel Sambuc 
2064684ddb6SLionel Sambuc void
get()2074684ddb6SLionel Sambuc future<void>::get()
2084684ddb6SLionel Sambuc {
2094684ddb6SLionel Sambuc     unique_ptr<__shared_count, __release_shared_count> __(__state_);
2104684ddb6SLionel Sambuc     __assoc_sub_state* __s = __state_;
2114684ddb6SLionel Sambuc     __state_ = nullptr;
2124684ddb6SLionel Sambuc     __s->copy();
2134684ddb6SLionel Sambuc }
2144684ddb6SLionel Sambuc 
promise()2154684ddb6SLionel Sambuc promise<void>::promise()
2164684ddb6SLionel Sambuc     : __state_(new __assoc_sub_state)
2174684ddb6SLionel Sambuc {
2184684ddb6SLionel Sambuc }
2194684ddb6SLionel Sambuc 
~promise()2204684ddb6SLionel Sambuc promise<void>::~promise()
2214684ddb6SLionel Sambuc {
2224684ddb6SLionel Sambuc     if (__state_)
2234684ddb6SLionel Sambuc     {
2244684ddb6SLionel Sambuc         if (!__state_->__has_value() && __state_->use_count() > 1)
2254684ddb6SLionel Sambuc             __state_->set_exception(make_exception_ptr(
2264684ddb6SLionel Sambuc                       future_error(make_error_code(future_errc::broken_promise))
2274684ddb6SLionel Sambuc                                                       ));
2284684ddb6SLionel Sambuc         __state_->__release_shared();
2294684ddb6SLionel Sambuc     }
2304684ddb6SLionel Sambuc }
2314684ddb6SLionel Sambuc 
2324684ddb6SLionel Sambuc future<void>
get_future()2334684ddb6SLionel Sambuc promise<void>::get_future()
2344684ddb6SLionel Sambuc {
2354684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
2364684ddb6SLionel Sambuc     if (__state_ == nullptr)
2374684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
2384684ddb6SLionel Sambuc #endif
2394684ddb6SLionel Sambuc     return future<void>(__state_);
2404684ddb6SLionel Sambuc }
2414684ddb6SLionel Sambuc 
2424684ddb6SLionel Sambuc void
set_value()2434684ddb6SLionel Sambuc promise<void>::set_value()
2444684ddb6SLionel Sambuc {
2454684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
2464684ddb6SLionel Sambuc     if (__state_ == nullptr)
2474684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
2484684ddb6SLionel Sambuc #endif
2494684ddb6SLionel Sambuc     __state_->set_value();
2504684ddb6SLionel Sambuc }
2514684ddb6SLionel Sambuc 
2524684ddb6SLionel Sambuc void
set_exception(exception_ptr __p)2534684ddb6SLionel Sambuc promise<void>::set_exception(exception_ptr __p)
2544684ddb6SLionel Sambuc {
2554684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
2564684ddb6SLionel Sambuc     if (__state_ == nullptr)
2574684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
2584684ddb6SLionel Sambuc #endif
2594684ddb6SLionel Sambuc     __state_->set_exception(__p);
2604684ddb6SLionel Sambuc }
2614684ddb6SLionel Sambuc 
2624684ddb6SLionel Sambuc void
set_value_at_thread_exit()2634684ddb6SLionel Sambuc promise<void>::set_value_at_thread_exit()
2644684ddb6SLionel Sambuc {
2654684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
2664684ddb6SLionel Sambuc     if (__state_ == nullptr)
2674684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
2684684ddb6SLionel Sambuc #endif
2694684ddb6SLionel Sambuc     __state_->set_value_at_thread_exit();
2704684ddb6SLionel Sambuc }
2714684ddb6SLionel Sambuc 
2724684ddb6SLionel Sambuc void
set_exception_at_thread_exit(exception_ptr __p)2734684ddb6SLionel Sambuc promise<void>::set_exception_at_thread_exit(exception_ptr __p)
2744684ddb6SLionel Sambuc {
2754684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
2764684ddb6SLionel Sambuc     if (__state_ == nullptr)
2774684ddb6SLionel Sambuc         throw future_error(make_error_code(future_errc::no_state));
2784684ddb6SLionel Sambuc #endif
2794684ddb6SLionel Sambuc     __state_->set_exception_at_thread_exit(__p);
2804684ddb6SLionel Sambuc }
2814684ddb6SLionel Sambuc 
~shared_future()2824684ddb6SLionel Sambuc shared_future<void>::~shared_future()
2834684ddb6SLionel Sambuc {
2844684ddb6SLionel Sambuc     if (__state_)
2854684ddb6SLionel Sambuc         __state_->__release_shared();
2864684ddb6SLionel Sambuc }
2874684ddb6SLionel Sambuc 
2884684ddb6SLionel Sambuc shared_future<void>&
operator =(const shared_future & __rhs)2894684ddb6SLionel Sambuc shared_future<void>::operator=(const shared_future& __rhs)
2904684ddb6SLionel Sambuc {
2914684ddb6SLionel Sambuc     if (__rhs.__state_)
2924684ddb6SLionel Sambuc         __rhs.__state_->__add_shared();
2934684ddb6SLionel Sambuc     if (__state_)
2944684ddb6SLionel Sambuc         __state_->__release_shared();
2954684ddb6SLionel Sambuc     __state_ = __rhs.__state_;
2964684ddb6SLionel Sambuc     return *this;
2974684ddb6SLionel Sambuc }
2984684ddb6SLionel Sambuc 
2994684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD
300*0a6a1f1dSLionel Sambuc 
301*0a6a1f1dSLionel Sambuc #endif // !_LIBCPP_HAS_NO_THREADS
302