xref: /llvm-project-15.0.7/libcxx/src/future.cpp (revision bbb0f2c7)
1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===//
2dae3481bSHoward Hinnant //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dae3481bSHoward Hinnant //
7dae3481bSHoward Hinnant //===----------------------------------------------------------------------===//
8dae3481bSHoward Hinnant 
9*bbb0f2c7SArthur O'Dwyer #include <__config>
10b3fcc67fSJonathan Roelofs 
11b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
12b3fcc67fSJonathan Roelofs 
13*bbb0f2c7SArthur O'Dwyer #include <future>
14*bbb0f2c7SArthur O'Dwyer #include <string>
15dae3481bSHoward Hinnant 
16dae3481bSHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD
17dae3481bSHoward Hinnant 
18dae3481bSHoward Hinnant class _LIBCPP_HIDDEN __future_error_category
19dae3481bSHoward Hinnant     : public __do_message
20dae3481bSHoward Hinnant {
21dae3481bSHoward Hinnant public:
225601305fSLouis Dionne     virtual const char* name() const noexcept;
23dae3481bSHoward Hinnant     virtual string message(int ev) const;
24dae3481bSHoward Hinnant };
25dae3481bSHoward Hinnant 
26dae3481bSHoward Hinnant const char*
name() const275601305fSLouis Dionne __future_error_category::name() const noexcept
28dae3481bSHoward Hinnant {
29dae3481bSHoward Hinnant     return "future";
30dae3481bSHoward Hinnant }
31dae3481bSHoward Hinnant 
32a7c2a628SNikolas Klauser _LIBCPP_DIAGNOSTIC_PUSH
33a7c2a628SNikolas Klauser _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")
34a7c2a628SNikolas Klauser _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")
353b2d7ee1SHoward Hinnant 
36dae3481bSHoward Hinnant string
message(int ev) const37dae3481bSHoward Hinnant __future_error_category::message(int ev) const
38dae3481bSHoward Hinnant {
39be745c8cSHoward Hinnant     switch (static_cast<future_errc>(ev))
40dae3481bSHoward Hinnant     {
413b2d7ee1SHoward Hinnant     case future_errc(0):  // For backwards compatibility with C++11 (LWG 2056)
42dae3481bSHoward Hinnant     case future_errc::broken_promise:
43dae3481bSHoward Hinnant         return string("The associated promise has been destructed prior "
44dae3481bSHoward Hinnant                       "to the associated state becoming ready.");
45dae3481bSHoward Hinnant     case future_errc::future_already_retrieved:
46dae3481bSHoward Hinnant         return string("The future has already been retrieved from "
47dae3481bSHoward Hinnant                       "the promise or packaged_task.");
48dae3481bSHoward Hinnant     case future_errc::promise_already_satisfied:
49dae3481bSHoward Hinnant         return string("The state of the promise has already been set.");
50dae3481bSHoward Hinnant     case future_errc::no_state:
51dae3481bSHoward Hinnant         return string("Operation not permitted on an object without "
52dae3481bSHoward Hinnant                       "an associated state.");
53dae3481bSHoward Hinnant     }
54dae3481bSHoward Hinnant     return string("unspecified future_errc value\n");
55dae3481bSHoward Hinnant }
56dae3481bSHoward Hinnant 
57a7c2a628SNikolas Klauser _LIBCPP_DIAGNOSTIC_POP
583b2d7ee1SHoward Hinnant 
59dae3481bSHoward Hinnant const error_category&
future_category()605601305fSLouis Dionne future_category() noexcept
61dae3481bSHoward Hinnant {
62dae3481bSHoward Hinnant     static __future_error_category __f;
63dae3481bSHoward Hinnant     return __f;
64dae3481bSHoward Hinnant }
65dae3481bSHoward Hinnant 
future_error(error_code __ec)66dae3481bSHoward Hinnant future_error::future_error(error_code __ec)
67dae3481bSHoward Hinnant     : logic_error(__ec.message()),
68dae3481bSHoward Hinnant       __ec_(__ec)
69dae3481bSHoward Hinnant {
70dae3481bSHoward Hinnant }
71dae3481bSHoward Hinnant 
~future_error()725601305fSLouis Dionne future_error::~future_error() noexcept
733aa229f7SHoward Hinnant {
743aa229f7SHoward Hinnant }
753aa229f7SHoward Hinnant 
76167fd108SHoward Hinnant void
__on_zero_shared()775601305fSLouis Dionne __assoc_sub_state::__on_zero_shared() noexcept
78167fd108SHoward Hinnant {
79167fd108SHoward Hinnant     delete this;
80167fd108SHoward Hinnant }
81167fd108SHoward Hinnant 
82167fd108SHoward Hinnant void
set_value()83167fd108SHoward Hinnant __assoc_sub_state::set_value()
84167fd108SHoward Hinnant {
85167fd108SHoward Hinnant     unique_lock<mutex> __lk(__mut_);
86167fd108SHoward Hinnant     if (__has_value())
87934864bfSMarshall Clow         __throw_future_error(future_errc::promise_already_satisfied);
88167fd108SHoward Hinnant     __state_ |= __constructed | ready;
89167fd108SHoward Hinnant     __cv_.notify_all();
90167fd108SHoward Hinnant }
91167fd108SHoward Hinnant 
92167fd108SHoward Hinnant void
set_value_at_thread_exit()93167fd108SHoward Hinnant __assoc_sub_state::set_value_at_thread_exit()
94167fd108SHoward Hinnant {
95167fd108SHoward Hinnant     unique_lock<mutex> __lk(__mut_);
96167fd108SHoward Hinnant     if (__has_value())
97934864bfSMarshall Clow         __throw_future_error(future_errc::promise_already_satisfied);
98167fd108SHoward Hinnant     __state_ |= __constructed;
9910e4a48aSHoward Hinnant     __thread_local_data()->__make_ready_at_thread_exit(this);
100167fd108SHoward Hinnant }
101167fd108SHoward Hinnant 
102167fd108SHoward Hinnant void
set_exception(exception_ptr __p)103167fd108SHoward Hinnant __assoc_sub_state::set_exception(exception_ptr __p)
104167fd108SHoward Hinnant {
105167fd108SHoward Hinnant     unique_lock<mutex> __lk(__mut_);
106167fd108SHoward Hinnant     if (__has_value())
107934864bfSMarshall Clow         __throw_future_error(future_errc::promise_already_satisfied);
108167fd108SHoward Hinnant     __exception_ = __p;
109167fd108SHoward Hinnant     __state_ |= ready;
110167fd108SHoward Hinnant     __cv_.notify_all();
111167fd108SHoward Hinnant }
112167fd108SHoward Hinnant 
113167fd108SHoward Hinnant void
set_exception_at_thread_exit(exception_ptr __p)114167fd108SHoward Hinnant __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
115167fd108SHoward Hinnant {
116167fd108SHoward Hinnant     unique_lock<mutex> __lk(__mut_);
117167fd108SHoward Hinnant     if (__has_value())
118934864bfSMarshall Clow         __throw_future_error(future_errc::promise_already_satisfied);
119167fd108SHoward Hinnant     __exception_ = __p;
12010e4a48aSHoward Hinnant     __thread_local_data()->__make_ready_at_thread_exit(this);
121167fd108SHoward Hinnant }
122167fd108SHoward Hinnant 
123167fd108SHoward Hinnant void
__make_ready()124167fd108SHoward Hinnant __assoc_sub_state::__make_ready()
125167fd108SHoward Hinnant {
126167fd108SHoward Hinnant     unique_lock<mutex> __lk(__mut_);
127167fd108SHoward Hinnant     __state_ |= ready;
128167fd108SHoward Hinnant     __cv_.notify_all();
129167fd108SHoward Hinnant }
130167fd108SHoward Hinnant 
131167fd108SHoward Hinnant void
copy()132167fd108SHoward Hinnant __assoc_sub_state::copy()
133167fd108SHoward Hinnant {
134167fd108SHoward Hinnant     unique_lock<mutex> __lk(__mut_);
13527f000e1SHoward Hinnant     __sub_wait(__lk);
136167fd108SHoward Hinnant     if (__exception_ != nullptr)
137167fd108SHoward Hinnant         rethrow_exception(__exception_);
138167fd108SHoward Hinnant }
139167fd108SHoward Hinnant 
140167fd108SHoward Hinnant void
wait()14127f000e1SHoward Hinnant __assoc_sub_state::wait()
142167fd108SHoward Hinnant {
143167fd108SHoward Hinnant     unique_lock<mutex> __lk(__mut_);
14427f000e1SHoward Hinnant     __sub_wait(__lk);
14527f000e1SHoward Hinnant }
14627f000e1SHoward Hinnant 
14727f000e1SHoward Hinnant void
__sub_wait(unique_lock<mutex> & __lk)14827f000e1SHoward Hinnant __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
14927f000e1SHoward Hinnant {
15027f000e1SHoward Hinnant     if (!__is_ready())
15127f000e1SHoward Hinnant     {
152c206366fSHoward Hinnant         if (__state_ & static_cast<unsigned>(deferred))
15327f000e1SHoward Hinnant         {
154c206366fSHoward Hinnant             __state_ &= ~static_cast<unsigned>(deferred);
15527f000e1SHoward Hinnant             __lk.unlock();
15627f000e1SHoward Hinnant             __execute();
15727f000e1SHoward Hinnant         }
15827f000e1SHoward Hinnant         else
159167fd108SHoward Hinnant             while (!__is_ready())
160167fd108SHoward Hinnant                 __cv_.wait(__lk);
161167fd108SHoward Hinnant     }
16227f000e1SHoward Hinnant }
16327f000e1SHoward Hinnant 
16427f000e1SHoward Hinnant void
__execute()16527f000e1SHoward Hinnant __assoc_sub_state::__execute()
16627f000e1SHoward Hinnant {
167934864bfSMarshall Clow     __throw_future_error(future_errc::no_state);
16827f000e1SHoward Hinnant }
169167fd108SHoward Hinnant 
future(__assoc_sub_state * __state)170167fd108SHoward Hinnant future<void>::future(__assoc_sub_state* __state)
171167fd108SHoward Hinnant     : __state_(__state)
172167fd108SHoward Hinnant {
173616ef186SLouis Dionne     __state_->__attach_future();
174167fd108SHoward Hinnant }
175167fd108SHoward Hinnant 
~future()176167fd108SHoward Hinnant future<void>::~future()
177167fd108SHoward Hinnant {
178167fd108SHoward Hinnant     if (__state_)
179167fd108SHoward Hinnant         __state_->__release_shared();
180167fd108SHoward Hinnant }
181167fd108SHoward Hinnant 
182167fd108SHoward Hinnant void
get()183167fd108SHoward Hinnant future<void>::get()
184167fd108SHoward Hinnant {
18527f000e1SHoward Hinnant     unique_ptr<__shared_count, __release_shared_count> __(__state_);
186167fd108SHoward Hinnant     __assoc_sub_state* __s = __state_;
187167fd108SHoward Hinnant     __state_ = nullptr;
18827f000e1SHoward Hinnant     __s->copy();
189167fd108SHoward Hinnant }
190167fd108SHoward Hinnant 
promise()191167fd108SHoward Hinnant promise<void>::promise()
192167fd108SHoward Hinnant     : __state_(new __assoc_sub_state)
193167fd108SHoward Hinnant {
194167fd108SHoward Hinnant }
195167fd108SHoward Hinnant 
~promise()196167fd108SHoward Hinnant promise<void>::~promise()
197167fd108SHoward Hinnant {
198167fd108SHoward Hinnant     if (__state_)
199167fd108SHoward Hinnant     {
200f520c144SAsiri Rathnayake #ifndef _LIBCPP_NO_EXCEPTIONS
201167fd108SHoward Hinnant         if (!__state_->__has_value() && __state_->use_count() > 1)
202167fd108SHoward Hinnant             __state_->set_exception(make_exception_ptr(
203167fd108SHoward Hinnant                       future_error(make_error_code(future_errc::broken_promise))
204167fd108SHoward Hinnant                                                       ));
205f520c144SAsiri Rathnayake #endif // _LIBCPP_NO_EXCEPTIONS
206167fd108SHoward Hinnant         __state_->__release_shared();
207167fd108SHoward Hinnant     }
208167fd108SHoward Hinnant }
209167fd108SHoward Hinnant 
210167fd108SHoward Hinnant future<void>
get_future()211167fd108SHoward Hinnant promise<void>::get_future()
212167fd108SHoward Hinnant {
213167fd108SHoward Hinnant     if (__state_ == nullptr)
214934864bfSMarshall Clow         __throw_future_error(future_errc::no_state);
215167fd108SHoward Hinnant     return future<void>(__state_);
216167fd108SHoward Hinnant }
217167fd108SHoward Hinnant 
218167fd108SHoward Hinnant void
set_value()219167fd108SHoward Hinnant promise<void>::set_value()
220167fd108SHoward Hinnant {
221167fd108SHoward Hinnant     if (__state_ == nullptr)
222934864bfSMarshall Clow         __throw_future_error(future_errc::no_state);
223167fd108SHoward Hinnant     __state_->set_value();
224167fd108SHoward Hinnant }
225167fd108SHoward Hinnant 
226167fd108SHoward Hinnant void
set_exception(exception_ptr __p)227167fd108SHoward Hinnant promise<void>::set_exception(exception_ptr __p)
228167fd108SHoward Hinnant {
229167fd108SHoward Hinnant     if (__state_ == nullptr)
230934864bfSMarshall Clow         __throw_future_error(future_errc::no_state);
231167fd108SHoward Hinnant     __state_->set_exception(__p);
232167fd108SHoward Hinnant }
233167fd108SHoward Hinnant 
234167fd108SHoward Hinnant void
set_value_at_thread_exit()235167fd108SHoward Hinnant promise<void>::set_value_at_thread_exit()
236167fd108SHoward Hinnant {
237167fd108SHoward Hinnant     if (__state_ == nullptr)
238934864bfSMarshall Clow         __throw_future_error(future_errc::no_state);
239167fd108SHoward Hinnant     __state_->set_value_at_thread_exit();
240167fd108SHoward Hinnant }
241167fd108SHoward Hinnant 
242167fd108SHoward Hinnant void
set_exception_at_thread_exit(exception_ptr __p)243167fd108SHoward Hinnant promise<void>::set_exception_at_thread_exit(exception_ptr __p)
244167fd108SHoward Hinnant {
245167fd108SHoward Hinnant     if (__state_ == nullptr)
246934864bfSMarshall Clow         __throw_future_error(future_errc::no_state);
247167fd108SHoward Hinnant     __state_->set_exception_at_thread_exit(__p);
248167fd108SHoward Hinnant }
249167fd108SHoward Hinnant 
~shared_future()250ead85506SHoward Hinnant shared_future<void>::~shared_future()
251ead85506SHoward Hinnant {
252ead85506SHoward Hinnant     if (__state_)
253ead85506SHoward Hinnant         __state_->__release_shared();
254ead85506SHoward Hinnant }
255ead85506SHoward Hinnant 
256ead85506SHoward Hinnant shared_future<void>&
operator =(const shared_future & __rhs)257ead85506SHoward Hinnant shared_future<void>::operator=(const shared_future& __rhs)
258ead85506SHoward Hinnant {
259ead85506SHoward Hinnant     if (__rhs.__state_)
260ead85506SHoward Hinnant         __rhs.__state_->__add_shared();
261ead85506SHoward Hinnant     if (__state_)
262ead85506SHoward Hinnant         __state_->__release_shared();
263ead85506SHoward Hinnant     __state_ = __rhs.__state_;
264ead85506SHoward Hinnant     return *this;
265ead85506SHoward Hinnant }
266ead85506SHoward Hinnant 
267dae3481bSHoward Hinnant _LIBCPP_END_NAMESPACE_STD
268b3fcc67fSJonathan Roelofs 
269b3fcc67fSJonathan Roelofs #endif // !_LIBCPP_HAS_NO_THREADS
270