blob: 29357112df9836bc68db595671cff0ec28d77ae3 [file] [log] [blame]
Howard Hinnanta6521722010-08-25 17:32:05 +00001//===------------------------- future.cpp ---------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnanta6521722010-08-25 17:32:05 +00007//
8//===----------------------------------------------------------------------===//
9
10#include "future"
11#include "string"
12
13_LIBCPP_BEGIN_NAMESPACE_STD
14
15class _LIBCPP_HIDDEN __future_error_category
16 : public __do_message
17{
18public:
Howard Hinnant1e15fd12011-05-26 19:48:01 +000019 virtual const char* name() const _NOEXCEPT;
Howard Hinnanta6521722010-08-25 17:32:05 +000020 virtual string message(int ev) const;
21};
22
23const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +000024__future_error_category::name() const _NOEXCEPT
Howard Hinnanta6521722010-08-25 17:32:05 +000025{
26 return "future";
27}
28
29string
30__future_error_category::message(int ev) const
31{
Howard Hinnantb1bc0c42012-02-02 20:31:36 +000032 switch (static_cast<future_errc>(ev))
Howard Hinnanta6521722010-08-25 17:32:05 +000033 {
34 case future_errc::broken_promise:
35 return string("The associated promise has been destructed prior "
36 "to the associated state becoming ready.");
37 case future_errc::future_already_retrieved:
38 return string("The future has already been retrieved from "
39 "the promise or packaged_task.");
40 case future_errc::promise_already_satisfied:
41 return string("The state of the promise has already been set.");
42 case future_errc::no_state:
43 return string("Operation not permitted on an object without "
44 "an associated state.");
45 }
46 return string("unspecified future_errc value\n");
47}
48
Howard Hinnanta6521722010-08-25 17:32:05 +000049const error_category&
50future_category()
51{
52 static __future_error_category __f;
53 return __f;
54}
55
56future_error::future_error(error_code __ec)
57 : logic_error(__ec.message()),
58 __ec_(__ec)
59{
60}
61
Howard Hinnant043fe1d2011-07-08 00:04:40 +000062future_error::~future_error() _NOEXCEPT
63{
64}
65
Howard Hinnant47499b12010-08-27 20:10:19 +000066void
Howard Hinnant1694d232011-05-28 14:41:13 +000067__assoc_sub_state::__on_zero_shared() _NOEXCEPT
Howard Hinnant47499b12010-08-27 20:10:19 +000068{
69 delete this;
70}
71
72void
73__assoc_sub_state::set_value()
74{
75 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +000076#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +000077 if (__has_value())
78 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +000079#endif
Howard Hinnant47499b12010-08-27 20:10:19 +000080 __state_ |= __constructed | ready;
81 __lk.unlock();
82 __cv_.notify_all();
83}
84
85void
86__assoc_sub_state::set_value_at_thread_exit()
87{
88 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +000089#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +000090 if (__has_value())
91 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +000092#endif
Howard Hinnant47499b12010-08-27 20:10:19 +000093 __state_ |= __constructed;
Howard Hinnant5306d682010-10-14 19:18:04 +000094 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +000095 __lk.unlock();
96}
97
98void
99__assoc_sub_state::set_exception(exception_ptr __p)
100{
101 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000102#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000103 if (__has_value())
104 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000105#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000106 __exception_ = __p;
107 __state_ |= ready;
108 __lk.unlock();
109 __cv_.notify_all();
110}
111
112void
113__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
114{
115 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000116#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000117 if (__has_value())
118 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000119#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000120 __exception_ = __p;
Howard Hinnant5306d682010-10-14 19:18:04 +0000121 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +0000122 __lk.unlock();
123}
124
125void
126__assoc_sub_state::__make_ready()
127{
128 unique_lock<mutex> __lk(__mut_);
129 __state_ |= ready;
130 __lk.unlock();
131 __cv_.notify_all();
132}
133
134void
135__assoc_sub_state::copy()
136{
137 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000138 __sub_wait(__lk);
Howard Hinnant47499b12010-08-27 20:10:19 +0000139 if (__exception_ != nullptr)
140 rethrow_exception(__exception_);
141}
142
143void
Howard Hinnant54da3382010-08-30 18:46:21 +0000144__assoc_sub_state::wait()
Howard Hinnant47499b12010-08-27 20:10:19 +0000145{
146 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000147 __sub_wait(__lk);
148}
149
150void
151__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
152{
153 if (!__is_ready())
154 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000155 if (__state_ & static_cast<unsigned>(deferred))
Howard Hinnant54da3382010-08-30 18:46:21 +0000156 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000157 __state_ &= ~static_cast<unsigned>(deferred);
Howard Hinnant54da3382010-08-30 18:46:21 +0000158 __lk.unlock();
159 __execute();
160 }
161 else
162 while (!__is_ready())
163 __cv_.wait(__lk);
164 }
165}
166
167void
168__assoc_sub_state::__execute()
169{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000170#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant54da3382010-08-30 18:46:21 +0000171 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000172#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000173}
174
175future<void>::future(__assoc_sub_state* __state)
176 : __state_(__state)
177{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000178#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000179 if (__state_->__has_future_attached())
180 throw future_error(make_error_code(future_errc::future_already_retrieved));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000181#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000182 __state_->__add_shared();
Howard Hinnant54da3382010-08-30 18:46:21 +0000183 __state_->__set_future_attached();
Howard Hinnant47499b12010-08-27 20:10:19 +0000184}
185
186future<void>::~future()
187{
188 if (__state_)
189 __state_->__release_shared();
190}
191
192void
193future<void>::get()
194{
Howard Hinnant54da3382010-08-30 18:46:21 +0000195 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant47499b12010-08-27 20:10:19 +0000196 __assoc_sub_state* __s = __state_;
197 __state_ = nullptr;
Howard Hinnant54da3382010-08-30 18:46:21 +0000198 __s->copy();
Howard Hinnant47499b12010-08-27 20:10:19 +0000199}
200
201promise<void>::promise()
202 : __state_(new __assoc_sub_state)
203{
204}
205
206promise<void>::~promise()
207{
208 if (__state_)
209 {
210 if (!__state_->__has_value() && __state_->use_count() > 1)
211 __state_->set_exception(make_exception_ptr(
212 future_error(make_error_code(future_errc::broken_promise))
213 ));
214 __state_->__release_shared();
215 }
216}
217
218future<void>
219promise<void>::get_future()
220{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000221#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000222 if (__state_ == nullptr)
223 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000224#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000225 return future<void>(__state_);
226}
227
228void
229promise<void>::set_value()
230{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000231#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000232 if (__state_ == nullptr)
233 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000234#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000235 __state_->set_value();
236}
237
238void
239promise<void>::set_exception(exception_ptr __p)
240{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000241#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000242 if (__state_ == nullptr)
243 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000244#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000245 __state_->set_exception(__p);
246}
247
248void
249promise<void>::set_value_at_thread_exit()
250{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000251#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000252 if (__state_ == nullptr)
253 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000254#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000255 __state_->set_value_at_thread_exit();
256}
257
258void
259promise<void>::set_exception_at_thread_exit(exception_ptr __p)
260{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000261#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000262 if (__state_ == nullptr)
263 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000264#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000265 __state_->set_exception_at_thread_exit(__p);
266}
267
Howard Hinnant99be8232010-09-03 18:39:25 +0000268shared_future<void>::~shared_future()
269{
270 if (__state_)
271 __state_->__release_shared();
272}
273
274shared_future<void>&
275shared_future<void>::operator=(const shared_future& __rhs)
276{
277 if (__rhs.__state_)
278 __rhs.__state_->__add_shared();
279 if (__state_)
280 __state_->__release_shared();
281 __state_ = __rhs.__state_;
282 return *this;
283}
284
Howard Hinnanta6521722010-08-25 17:32:05 +0000285_LIBCPP_END_NAMESPACE_STD