blob: 70919ab7df84aa4e6f035ae273dcbc9328f40ad2 [file] [log] [blame]
Howard Hinnant96803d92010-08-25 17:32:05 +00001//===------------------------- future.cpp ---------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Howard Hinnantee11c312010-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 Hinnant96803d92010-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 Hinnant1f098bc2011-05-26 19:48:01 +000019 virtual const char* name() const _NOEXCEPT;
Howard Hinnant96803d92010-08-25 17:32:05 +000020 virtual string message(int ev) const;
21};
22
23const char*
Howard Hinnant1f098bc2011-05-26 19:48:01 +000024__future_error_category::name() const _NOEXCEPT
Howard Hinnant96803d92010-08-25 17:32:05 +000025{
26 return "future";
27}
28
Howard Hinnantf2fd64d2013-09-14 18:20:10 +000029#pragma clang diagnostic push
30#pragma clang diagnostic ignored "-Wswitch"
31
Howard Hinnant96803d92010-08-25 17:32:05 +000032string
33__future_error_category::message(int ev) const
34{
Howard Hinnant5afe2522012-02-02 20:31:36 +000035 switch (static_cast<future_errc>(ev))
Howard Hinnant96803d92010-08-25 17:32:05 +000036 {
Howard Hinnantf2fd64d2013-09-14 18:20:10 +000037 case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)
Howard Hinnant96803d92010-08-25 17:32:05 +000038 case future_errc::broken_promise:
39 return string("The associated promise has been destructed prior "
40 "to the associated state becoming ready.");
41 case future_errc::future_already_retrieved:
42 return string("The future has already been retrieved from "
43 "the promise or packaged_task.");
44 case future_errc::promise_already_satisfied:
45 return string("The state of the promise has already been set.");
46 case future_errc::no_state:
47 return string("Operation not permitted on an object without "
48 "an associated state.");
49 }
50 return string("unspecified future_errc value\n");
51}
52
Howard Hinnantf2fd64d2013-09-14 18:20:10 +000053#pragma clang diagnostic pop
54
Howard Hinnant96803d92010-08-25 17:32:05 +000055const error_category&
Howard Hinnant22448042012-07-21 17:46:55 +000056future_category() _NOEXCEPT
Howard Hinnant96803d92010-08-25 17:32:05 +000057{
58 static __future_error_category __f;
59 return __f;
60}
61
62future_error::future_error(error_code __ec)
63 : logic_error(__ec.message()),
64 __ec_(__ec)
65{
66}
67
Howard Hinnant5e0c5212011-07-08 00:04:40 +000068future_error::~future_error() _NOEXCEPT
69{
70}
71
Howard Hinnant3820f6b2010-08-27 20:10:19 +000072void
Howard Hinnant719bda32011-05-28 14:41:13 +000073__assoc_sub_state::__on_zero_shared() _NOEXCEPT
Howard Hinnant3820f6b2010-08-27 20:10:19 +000074{
75 delete this;
76}
77
78void
79__assoc_sub_state::set_value()
80{
81 unique_lock<mutex> __lk(__mut_);
Howard Hinnant83e6aad2011-07-13 16:00:50 +000082#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +000083 if (__has_value())
84 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant83e6aad2011-07-13 16:00:50 +000085#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +000086 __state_ |= __constructed | ready;
Howard Hinnant3820f6b2010-08-27 20:10:19 +000087 __cv_.notify_all();
Howard Hinnante667ecc2013-01-14 20:01:24 +000088 __lk.unlock();
Howard Hinnant3820f6b2010-08-27 20:10:19 +000089}
90
91void
92__assoc_sub_state::set_value_at_thread_exit()
93{
94 unique_lock<mutex> __lk(__mut_);
Howard Hinnant83e6aad2011-07-13 16:00:50 +000095#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +000096 if (__has_value())
97 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant83e6aad2011-07-13 16:00:50 +000098#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +000099 __state_ |= __constructed;
Howard Hinnant15d55052010-10-14 19:18:04 +0000100 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000101 __lk.unlock();
102}
103
104void
105__assoc_sub_state::set_exception(exception_ptr __p)
106{
107 unique_lock<mutex> __lk(__mut_);
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000108#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000109 if (__has_value())
110 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000111#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000112 __exception_ = __p;
113 __state_ |= ready;
114 __lk.unlock();
115 __cv_.notify_all();
116}
117
118void
119__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
120{
121 unique_lock<mutex> __lk(__mut_);
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000122#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000123 if (__has_value())
124 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000125#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000126 __exception_ = __p;
Howard Hinnant15d55052010-10-14 19:18:04 +0000127 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000128 __lk.unlock();
129}
130
131void
132__assoc_sub_state::__make_ready()
133{
134 unique_lock<mutex> __lk(__mut_);
135 __state_ |= ready;
136 __lk.unlock();
137 __cv_.notify_all();
138}
139
140void
141__assoc_sub_state::copy()
142{
143 unique_lock<mutex> __lk(__mut_);
Howard Hinnantccdd2032010-08-30 18:46:21 +0000144 __sub_wait(__lk);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000145 if (__exception_ != nullptr)
146 rethrow_exception(__exception_);
147}
148
149void
Howard Hinnantccdd2032010-08-30 18:46:21 +0000150__assoc_sub_state::wait()
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000151{
152 unique_lock<mutex> __lk(__mut_);
Howard Hinnantccdd2032010-08-30 18:46:21 +0000153 __sub_wait(__lk);
154}
155
156void
157__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
158{
159 if (!__is_ready())
160 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000161 if (__state_ & static_cast<unsigned>(deferred))
Howard Hinnantccdd2032010-08-30 18:46:21 +0000162 {
Howard Hinnant28b24882011-12-01 20:21:04 +0000163 __state_ &= ~static_cast<unsigned>(deferred);
Howard Hinnantccdd2032010-08-30 18:46:21 +0000164 __lk.unlock();
165 __execute();
166 }
167 else
168 while (!__is_ready())
169 __cv_.wait(__lk);
170 }
171}
172
173void
174__assoc_sub_state::__execute()
175{
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000176#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantccdd2032010-08-30 18:46:21 +0000177 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000178#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000179}
180
181future<void>::future(__assoc_sub_state* __state)
182 : __state_(__state)
183{
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000184#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000185 if (__state_->__has_future_attached())
186 throw future_error(make_error_code(future_errc::future_already_retrieved));
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000187#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000188 __state_->__add_shared();
Howard Hinnantccdd2032010-08-30 18:46:21 +0000189 __state_->__set_future_attached();
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000190}
191
192future<void>::~future()
193{
194 if (__state_)
195 __state_->__release_shared();
196}
197
198void
199future<void>::get()
200{
Howard Hinnantccdd2032010-08-30 18:46:21 +0000201 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000202 __assoc_sub_state* __s = __state_;
203 __state_ = nullptr;
Howard Hinnantccdd2032010-08-30 18:46:21 +0000204 __s->copy();
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000205}
206
207promise<void>::promise()
208 : __state_(new __assoc_sub_state)
209{
210}
211
212promise<void>::~promise()
213{
214 if (__state_)
215 {
216 if (!__state_->__has_value() && __state_->use_count() > 1)
217 __state_->set_exception(make_exception_ptr(
218 future_error(make_error_code(future_errc::broken_promise))
219 ));
220 __state_->__release_shared();
221 }
222}
223
224future<void>
225promise<void>::get_future()
226{
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000227#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000228 if (__state_ == nullptr)
229 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000230#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000231 return future<void>(__state_);
232}
233
234void
235promise<void>::set_value()
236{
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000237#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000238 if (__state_ == nullptr)
239 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000240#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000241 __state_->set_value();
242}
243
244void
245promise<void>::set_exception(exception_ptr __p)
246{
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000247#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000248 if (__state_ == nullptr)
249 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000250#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000251 __state_->set_exception(__p);
252}
253
254void
255promise<void>::set_value_at_thread_exit()
256{
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000257#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000258 if (__state_ == nullptr)
259 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000260#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000261 __state_->set_value_at_thread_exit();
262}
263
264void
265promise<void>::set_exception_at_thread_exit(exception_ptr __p)
266{
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000267#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000268 if (__state_ == nullptr)
269 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant83e6aad2011-07-13 16:00:50 +0000270#endif
Howard Hinnant3820f6b2010-08-27 20:10:19 +0000271 __state_->set_exception_at_thread_exit(__p);
272}
273
Howard Hinnant92646c42010-09-03 18:39:25 +0000274shared_future<void>::~shared_future()
275{
276 if (__state_)
277 __state_->__release_shared();
278}
279
280shared_future<void>&
281shared_future<void>::operator=(const shared_future& __rhs)
282{
283 if (__rhs.__state_)
284 __rhs.__state_->__add_shared();
285 if (__state_)
286 __state_->__release_shared();
287 __state_ = __rhs.__state_;
288 return *this;
289}
290
Howard Hinnant96803d92010-08-25 17:32:05 +0000291_LIBCPP_END_NAMESPACE_STD