blob: 4c3a3fa8b982a7dfd62ecbe2d137dee38d566c7c [file] [log] [blame]
Howard Hinnantdae34812010-08-25 17:32:051//===------------------------- future.cpp ---------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Howard Hinnant412dbeb2010-11-16 22:09:025// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantdae34812010-08-25 17:32:057//
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 Hinnanta62f2892011-05-26 19:48:0119 virtual const char* name() const _NOEXCEPT;
Howard Hinnantdae34812010-08-25 17:32:0520 virtual string message(int ev) const;
21};
22
23const char*
Howard Hinnanta62f2892011-05-26 19:48:0124__future_error_category::name() const _NOEXCEPT
Howard Hinnantdae34812010-08-25 17:32:0525{
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 Hinnantdae34812010-08-25 17:32:0549const 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 Hinnant3aa229f2011-07-08 00:04:4062future_error::~future_error() _NOEXCEPT
63{
64}
65
Howard Hinnant167fd102010-08-27 20:10:1966void
Howard Hinnant3739fe72011-05-28 14:41:1367__assoc_sub_state::__on_zero_shared() _NOEXCEPT
Howard Hinnant167fd102010-08-27 20:10:1968{
69 delete this;
70}
71
72void
73__assoc_sub_state::set_value()
74{
75 unique_lock<mutex> __lk(__mut_);
76 if (__has_value())
77 throw future_error(make_error_code(future_errc::promise_already_satisfied));
78 __state_ |= __constructed | ready;
79 __lk.unlock();
80 __cv_.notify_all();
81}
82
83void
84__assoc_sub_state::set_value_at_thread_exit()
85{
86 unique_lock<mutex> __lk(__mut_);
87 if (__has_value())
88 throw future_error(make_error_code(future_errc::promise_already_satisfied));
89 __state_ |= __constructed;
Howard Hinnant10e4a482010-10-14 19:18:0490 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant167fd102010-08-27 20:10:1991 __lk.unlock();
92}
93
94void
95__assoc_sub_state::set_exception(exception_ptr __p)
96{
97 unique_lock<mutex> __lk(__mut_);
98 if (__has_value())
99 throw future_error(make_error_code(future_errc::promise_already_satisfied));
100 __exception_ = __p;
101 __state_ |= ready;
102 __lk.unlock();
103 __cv_.notify_all();
104}
105
106void
107__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
108{
109 unique_lock<mutex> __lk(__mut_);
110 if (__has_value())
111 throw future_error(make_error_code(future_errc::promise_already_satisfied));
112 __exception_ = __p;
Howard Hinnant10e4a482010-10-14 19:18:04113 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant167fd102010-08-27 20:10:19114 __lk.unlock();
115}
116
117void
118__assoc_sub_state::__make_ready()
119{
120 unique_lock<mutex> __lk(__mut_);
121 __state_ |= ready;
122 __lk.unlock();
123 __cv_.notify_all();
124}
125
126void
127__assoc_sub_state::copy()
128{
129 unique_lock<mutex> __lk(__mut_);
Howard Hinnant27f000e2010-08-30 18:46:21130 __sub_wait(__lk);
Howard Hinnant167fd102010-08-27 20:10:19131 if (__exception_ != nullptr)
132 rethrow_exception(__exception_);
133}
134
135void
Howard Hinnant27f000e2010-08-30 18:46:21136__assoc_sub_state::wait()
Howard Hinnant167fd102010-08-27 20:10:19137{
138 unique_lock<mutex> __lk(__mut_);
Howard Hinnant27f000e2010-08-30 18:46:21139 __sub_wait(__lk);
140}
141
142void
143__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
144{
145 if (!__is_ready())
146 {
147 if (__state_ & deferred)
148 {
149 __state_ &= ~deferred;
150 __lk.unlock();
151 __execute();
152 }
153 else
154 while (!__is_ready())
155 __cv_.wait(__lk);
156 }
157}
158
159void
160__assoc_sub_state::__execute()
161{
162 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant167fd102010-08-27 20:10:19163}
164
165future<void>::future(__assoc_sub_state* __state)
166 : __state_(__state)
167{
168 if (__state_->__has_future_attached())
169 throw future_error(make_error_code(future_errc::future_already_retrieved));
170 __state_->__add_shared();
Howard Hinnant27f000e2010-08-30 18:46:21171 __state_->__set_future_attached();
Howard Hinnant167fd102010-08-27 20:10:19172}
173
174future<void>::~future()
175{
176 if (__state_)
177 __state_->__release_shared();
178}
179
180void
181future<void>::get()
182{
Howard Hinnant27f000e2010-08-30 18:46:21183 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant167fd102010-08-27 20:10:19184 __assoc_sub_state* __s = __state_;
185 __state_ = nullptr;
Howard Hinnant27f000e2010-08-30 18:46:21186 __s->copy();
Howard Hinnant167fd102010-08-27 20:10:19187}
188
189promise<void>::promise()
190 : __state_(new __assoc_sub_state)
191{
192}
193
194promise<void>::~promise()
195{
196 if (__state_)
197 {
198 if (!__state_->__has_value() && __state_->use_count() > 1)
199 __state_->set_exception(make_exception_ptr(
200 future_error(make_error_code(future_errc::broken_promise))
201 ));
202 __state_->__release_shared();
203 }
204}
205
206future<void>
207promise<void>::get_future()
208{
209 if (__state_ == nullptr)
210 throw future_error(make_error_code(future_errc::no_state));
211 return future<void>(__state_);
212}
213
214void
215promise<void>::set_value()
216{
217 if (__state_ == nullptr)
218 throw future_error(make_error_code(future_errc::no_state));
219 __state_->set_value();
220}
221
222void
223promise<void>::set_exception(exception_ptr __p)
224{
225 if (__state_ == nullptr)
226 throw future_error(make_error_code(future_errc::no_state));
227 __state_->set_exception(__p);
228}
229
230void
231promise<void>::set_value_at_thread_exit()
232{
233 if (__state_ == nullptr)
234 throw future_error(make_error_code(future_errc::no_state));
235 __state_->set_value_at_thread_exit();
236}
237
238void
239promise<void>::set_exception_at_thread_exit(exception_ptr __p)
240{
241 if (__state_ == nullptr)
242 throw future_error(make_error_code(future_errc::no_state));
243 __state_->set_exception_at_thread_exit(__p);
244}
245
Howard Hinnantead85502010-09-03 18:39:25246shared_future<void>::~shared_future()
247{
248 if (__state_)
249 __state_->__release_shared();
250}
251
252shared_future<void>&
253shared_future<void>::operator=(const shared_future& __rhs)
254{
255 if (__rhs.__state_)
256 __rhs.__state_->__add_shared();
257 if (__state_)
258 __state_->__release_shared();
259 __state_ = __rhs.__state_;
260 return *this;
261}
262
Howard Hinnantdae34812010-08-25 17:32:05263_LIBCPP_END_NAMESPACE_STD