blob: a008276712217bf52feae24ddc718eba85aebf70 [file] [log] [blame]
Howard Hinnantdae34812010-08-25 17:32:051//===------------------------- future.cpp ---------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
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:
19 virtual const char* name() const;
20 virtual string message(int ev) const;
21};
22
23const char*
24__future_error_category::name() const
25{
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
49
50const error_category&
51future_category()
52{
53 static __future_error_category __f;
54 return __f;
55}
56
57future_error::future_error(error_code __ec)
58 : logic_error(__ec.message()),
59 __ec_(__ec)
60{
61}
62
Howard Hinnant167fd102010-08-27 20:10:1963void
64__assoc_sub_state::__on_zero_shared()
65{
66 delete this;
67}
68
69void
70__assoc_sub_state::set_value()
71{
72 unique_lock<mutex> __lk(__mut_);
73 if (__has_value())
74 throw future_error(make_error_code(future_errc::promise_already_satisfied));
75 __state_ |= __constructed | ready;
76 __lk.unlock();
77 __cv_.notify_all();
78}
79
80void
81__assoc_sub_state::set_value_at_thread_exit()
82{
83 unique_lock<mutex> __lk(__mut_);
84 if (__has_value())
85 throw future_error(make_error_code(future_errc::promise_already_satisfied));
86 __state_ |= __constructed;
87 __thread_local_data->__make_ready_at_thread_exit(this);
88 __lk.unlock();
89}
90
91void
92__assoc_sub_state::set_exception(exception_ptr __p)
93{
94 unique_lock<mutex> __lk(__mut_);
95 if (__has_value())
96 throw future_error(make_error_code(future_errc::promise_already_satisfied));
97 __exception_ = __p;
98 __state_ |= ready;
99 __lk.unlock();
100 __cv_.notify_all();
101}
102
103void
104__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
105{
106 unique_lock<mutex> __lk(__mut_);
107 if (__has_value())
108 throw future_error(make_error_code(future_errc::promise_already_satisfied));
109 __exception_ = __p;
110 __thread_local_data->__make_ready_at_thread_exit(this);
111 __lk.unlock();
112}
113
114void
115__assoc_sub_state::__make_ready()
116{
117 unique_lock<mutex> __lk(__mut_);
118 __state_ |= ready;
119 __lk.unlock();
120 __cv_.notify_all();
121}
122
123void
124__assoc_sub_state::copy()
125{
126 unique_lock<mutex> __lk(__mut_);
Howard Hinnant27f000e2010-08-30 18:46:21127 __sub_wait(__lk);
Howard Hinnant167fd102010-08-27 20:10:19128 if (__exception_ != nullptr)
129 rethrow_exception(__exception_);
130}
131
132void
Howard Hinnant27f000e2010-08-30 18:46:21133__assoc_sub_state::wait()
Howard Hinnant167fd102010-08-27 20:10:19134{
135 unique_lock<mutex> __lk(__mut_);
Howard Hinnant27f000e2010-08-30 18:46:21136 __sub_wait(__lk);
137}
138
139void
140__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
141{
142 if (!__is_ready())
143 {
144 if (__state_ & deferred)
145 {
146 __state_ &= ~deferred;
147 __lk.unlock();
148 __execute();
149 }
150 else
151 while (!__is_ready())
152 __cv_.wait(__lk);
153 }
154}
155
156void
157__assoc_sub_state::__execute()
158{
159 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant167fd102010-08-27 20:10:19160}
161
162future<void>::future(__assoc_sub_state* __state)
163 : __state_(__state)
164{
165 if (__state_->__has_future_attached())
166 throw future_error(make_error_code(future_errc::future_already_retrieved));
167 __state_->__add_shared();
Howard Hinnant27f000e2010-08-30 18:46:21168 __state_->__set_future_attached();
Howard Hinnant167fd102010-08-27 20:10:19169}
170
171future<void>::~future()
172{
173 if (__state_)
174 __state_->__release_shared();
175}
176
177void
178future<void>::get()
179{
Howard Hinnant27f000e2010-08-30 18:46:21180 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant167fd102010-08-27 20:10:19181 __assoc_sub_state* __s = __state_;
182 __state_ = nullptr;
Howard Hinnant27f000e2010-08-30 18:46:21183 __s->copy();
Howard Hinnant167fd102010-08-27 20:10:19184}
185
186promise<void>::promise()
187 : __state_(new __assoc_sub_state)
188{
189}
190
191promise<void>::~promise()
192{
193 if (__state_)
194 {
195 if (!__state_->__has_value() && __state_->use_count() > 1)
196 __state_->set_exception(make_exception_ptr(
197 future_error(make_error_code(future_errc::broken_promise))
198 ));
199 __state_->__release_shared();
200 }
201}
202
203future<void>
204promise<void>::get_future()
205{
206 if (__state_ == nullptr)
207 throw future_error(make_error_code(future_errc::no_state));
208 return future<void>(__state_);
209}
210
211void
212promise<void>::set_value()
213{
214 if (__state_ == nullptr)
215 throw future_error(make_error_code(future_errc::no_state));
216 __state_->set_value();
217}
218
219void
220promise<void>::set_exception(exception_ptr __p)
221{
222 if (__state_ == nullptr)
223 throw future_error(make_error_code(future_errc::no_state));
224 __state_->set_exception(__p);
225}
226
227void
228promise<void>::set_value_at_thread_exit()
229{
230 if (__state_ == nullptr)
231 throw future_error(make_error_code(future_errc::no_state));
232 __state_->set_value_at_thread_exit();
233}
234
235void
236promise<void>::set_exception_at_thread_exit(exception_ptr __p)
237{
238 if (__state_ == nullptr)
239 throw future_error(make_error_code(future_errc::no_state));
240 __state_->set_exception_at_thread_exit(__p);
241}
242
Howard Hinnantdae34812010-08-25 17:32:05243_LIBCPP_END_NAMESPACE_STD