blob: 98c78055ca9599e16804afaa9393839397220022 [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{
32 switch (ev)
33 {
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 Hinnant47499b12010-08-27 20:10:19 +000062void
Howard Hinnant1694d232011-05-28 14:41:13 +000063__assoc_sub_state::__on_zero_shared() _NOEXCEPT
Howard Hinnant47499b12010-08-27 20:10:19 +000064{
65 delete this;
66}
67
68void
69__assoc_sub_state::set_value()
70{
71 unique_lock<mutex> __lk(__mut_);
72 if (__has_value())
73 throw future_error(make_error_code(future_errc::promise_already_satisfied));
74 __state_ |= __constructed | ready;
75 __lk.unlock();
76 __cv_.notify_all();
77}
78
79void
80__assoc_sub_state::set_value_at_thread_exit()
81{
82 unique_lock<mutex> __lk(__mut_);
83 if (__has_value())
84 throw future_error(make_error_code(future_errc::promise_already_satisfied));
85 __state_ |= __constructed;
Howard Hinnant5306d682010-10-14 19:18:04 +000086 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +000087 __lk.unlock();
88}
89
90void
91__assoc_sub_state::set_exception(exception_ptr __p)
92{
93 unique_lock<mutex> __lk(__mut_);
94 if (__has_value())
95 throw future_error(make_error_code(future_errc::promise_already_satisfied));
96 __exception_ = __p;
97 __state_ |= ready;
98 __lk.unlock();
99 __cv_.notify_all();
100}
101
102void
103__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
104{
105 unique_lock<mutex> __lk(__mut_);
106 if (__has_value())
107 throw future_error(make_error_code(future_errc::promise_already_satisfied));
108 __exception_ = __p;
Howard Hinnant5306d682010-10-14 19:18:04 +0000109 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +0000110 __lk.unlock();
111}
112
113void
114__assoc_sub_state::__make_ready()
115{
116 unique_lock<mutex> __lk(__mut_);
117 __state_ |= ready;
118 __lk.unlock();
119 __cv_.notify_all();
120}
121
122void
123__assoc_sub_state::copy()
124{
125 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000126 __sub_wait(__lk);
Howard Hinnant47499b12010-08-27 20:10:19 +0000127 if (__exception_ != nullptr)
128 rethrow_exception(__exception_);
129}
130
131void
Howard Hinnant54da3382010-08-30 18:46:21 +0000132__assoc_sub_state::wait()
Howard Hinnant47499b12010-08-27 20:10:19 +0000133{
134 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000135 __sub_wait(__lk);
136}
137
138void
139__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
140{
141 if (!__is_ready())
142 {
143 if (__state_ & deferred)
144 {
145 __state_ &= ~deferred;
146 __lk.unlock();
147 __execute();
148 }
149 else
150 while (!__is_ready())
151 __cv_.wait(__lk);
152 }
153}
154
155void
156__assoc_sub_state::__execute()
157{
158 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant47499b12010-08-27 20:10:19 +0000159}
160
161future<void>::future(__assoc_sub_state* __state)
162 : __state_(__state)
163{
164 if (__state_->__has_future_attached())
165 throw future_error(make_error_code(future_errc::future_already_retrieved));
166 __state_->__add_shared();
Howard Hinnant54da3382010-08-30 18:46:21 +0000167 __state_->__set_future_attached();
Howard Hinnant47499b12010-08-27 20:10:19 +0000168}
169
170future<void>::~future()
171{
172 if (__state_)
173 __state_->__release_shared();
174}
175
176void
177future<void>::get()
178{
Howard Hinnant54da3382010-08-30 18:46:21 +0000179 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant47499b12010-08-27 20:10:19 +0000180 __assoc_sub_state* __s = __state_;
181 __state_ = nullptr;
Howard Hinnant54da3382010-08-30 18:46:21 +0000182 __s->copy();
Howard Hinnant47499b12010-08-27 20:10:19 +0000183}
184
185promise<void>::promise()
186 : __state_(new __assoc_sub_state)
187{
188}
189
190promise<void>::~promise()
191{
192 if (__state_)
193 {
194 if (!__state_->__has_value() && __state_->use_count() > 1)
195 __state_->set_exception(make_exception_ptr(
196 future_error(make_error_code(future_errc::broken_promise))
197 ));
198 __state_->__release_shared();
199 }
200}
201
202future<void>
203promise<void>::get_future()
204{
205 if (__state_ == nullptr)
206 throw future_error(make_error_code(future_errc::no_state));
207 return future<void>(__state_);
208}
209
210void
211promise<void>::set_value()
212{
213 if (__state_ == nullptr)
214 throw future_error(make_error_code(future_errc::no_state));
215 __state_->set_value();
216}
217
218void
219promise<void>::set_exception(exception_ptr __p)
220{
221 if (__state_ == nullptr)
222 throw future_error(make_error_code(future_errc::no_state));
223 __state_->set_exception(__p);
224}
225
226void
227promise<void>::set_value_at_thread_exit()
228{
229 if (__state_ == nullptr)
230 throw future_error(make_error_code(future_errc::no_state));
231 __state_->set_value_at_thread_exit();
232}
233
234void
235promise<void>::set_exception_at_thread_exit(exception_ptr __p)
236{
237 if (__state_ == nullptr)
238 throw future_error(make_error_code(future_errc::no_state));
239 __state_->set_exception_at_thread_exit(__p);
240}
241
Howard Hinnant99be8232010-09-03 18:39:25 +0000242shared_future<void>::~shared_future()
243{
244 if (__state_)
245 __state_->__release_shared();
246}
247
248shared_future<void>&
249shared_future<void>::operator=(const shared_future& __rhs)
250{
251 if (__rhs.__state_)
252 __rhs.__state_->__add_shared();
253 if (__state_)
254 __state_->__release_shared();
255 __state_ = __rhs.__state_;
256 return *this;
257}
258
Howard Hinnanta6521722010-08-25 17:32:05 +0000259_LIBCPP_END_NAMESPACE_STD