]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/libc++/src/future.cpp
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / libc++ / src / future.cpp
1 //===------------------------- future.cpp ---------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "future"
11 #include "string"
12
13 _LIBCPP_BEGIN_NAMESPACE_STD
14
15 class _LIBCPP_HIDDEN __future_error_category
16     : public __do_message
17 {
18 public:
19     virtual const char* name() const _NOEXCEPT;
20     virtual string message(int ev) const;
21 };
22
23 const char*
24 __future_error_category::name() const _NOEXCEPT
25 {
26     return "future";
27 }
28
29 string
30 __future_error_category::message(int ev) const
31 {
32     switch (static_cast<future_errc>(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 const error_category&
50 future_category() _NOEXCEPT
51 {
52     static __future_error_category __f;
53     return __f;
54 }
55
56 future_error::future_error(error_code __ec)
57     : logic_error(__ec.message()),
58       __ec_(__ec)
59 {
60 }
61
62 future_error::~future_error() _NOEXCEPT
63 {
64 }
65
66 void
67 __assoc_sub_state::__on_zero_shared() _NOEXCEPT
68 {
69     delete this;
70 }
71
72 void
73 __assoc_sub_state::set_value()
74 {
75     unique_lock<mutex> __lk(__mut_);
76 #ifndef _LIBCPP_NO_EXCEPTIONS
77     if (__has_value())
78         throw future_error(make_error_code(future_errc::promise_already_satisfied));
79 #endif
80     __state_ |= __constructed | ready;
81     __cv_.notify_all();
82     __lk.unlock();
83 }
84
85 void
86 __assoc_sub_state::set_value_at_thread_exit()
87 {
88     unique_lock<mutex> __lk(__mut_);
89 #ifndef _LIBCPP_NO_EXCEPTIONS
90     if (__has_value())
91         throw future_error(make_error_code(future_errc::promise_already_satisfied));
92 #endif
93     __state_ |= __constructed;
94     __thread_local_data()->__make_ready_at_thread_exit(this);
95     __lk.unlock();
96 }
97
98 void
99 __assoc_sub_state::set_exception(exception_ptr __p)
100 {
101     unique_lock<mutex> __lk(__mut_);
102 #ifndef _LIBCPP_NO_EXCEPTIONS
103     if (__has_value())
104         throw future_error(make_error_code(future_errc::promise_already_satisfied));
105 #endif
106     __exception_ = __p;
107     __state_ |= ready;
108     __lk.unlock();
109     __cv_.notify_all();
110 }
111
112 void
113 __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
114 {
115     unique_lock<mutex> __lk(__mut_);
116 #ifndef _LIBCPP_NO_EXCEPTIONS
117     if (__has_value())
118         throw future_error(make_error_code(future_errc::promise_already_satisfied));
119 #endif
120     __exception_ = __p;
121     __thread_local_data()->__make_ready_at_thread_exit(this);
122     __lk.unlock();
123 }
124
125 void
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
134 void
135 __assoc_sub_state::copy()
136 {
137     unique_lock<mutex> __lk(__mut_);
138     __sub_wait(__lk);
139     if (__exception_ != nullptr)
140         rethrow_exception(__exception_);
141 }
142
143 void
144 __assoc_sub_state::wait()
145 {
146     unique_lock<mutex> __lk(__mut_);
147     __sub_wait(__lk);
148 }
149
150 void
151 __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
152 {
153     if (!__is_ready())
154     {
155         if (__state_ & static_cast<unsigned>(deferred))
156         {
157             __state_ &= ~static_cast<unsigned>(deferred);
158             __lk.unlock();
159             __execute();
160         }
161         else
162             while (!__is_ready())
163                 __cv_.wait(__lk);
164     }
165 }
166
167 void
168 __assoc_sub_state::__execute()
169 {
170 #ifndef _LIBCPP_NO_EXCEPTIONS
171     throw future_error(make_error_code(future_errc::no_state));
172 #endif
173 }
174
175 future<void>::future(__assoc_sub_state* __state)
176     : __state_(__state)
177 {
178 #ifndef _LIBCPP_NO_EXCEPTIONS
179     if (__state_->__has_future_attached())
180         throw future_error(make_error_code(future_errc::future_already_retrieved));
181 #endif
182     __state_->__add_shared();
183     __state_->__set_future_attached();
184 }
185
186 future<void>::~future()
187 {
188     if (__state_)
189         __state_->__release_shared();
190 }
191
192 void
193 future<void>::get()
194 {
195     unique_ptr<__shared_count, __release_shared_count> __(__state_);
196     __assoc_sub_state* __s = __state_;
197     __state_ = nullptr;
198     __s->copy();
199 }
200
201 promise<void>::promise()
202     : __state_(new __assoc_sub_state)
203 {
204 }
205
206 promise<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
218 future<void>
219 promise<void>::get_future()
220 {
221 #ifndef _LIBCPP_NO_EXCEPTIONS
222     if (__state_ == nullptr)
223         throw future_error(make_error_code(future_errc::no_state));
224 #endif
225     return future<void>(__state_);
226 }
227
228 void
229 promise<void>::set_value()
230 {
231 #ifndef _LIBCPP_NO_EXCEPTIONS
232     if (__state_ == nullptr)
233         throw future_error(make_error_code(future_errc::no_state));
234 #endif
235     __state_->set_value();
236 }
237
238 void
239 promise<void>::set_exception(exception_ptr __p)
240 {
241 #ifndef _LIBCPP_NO_EXCEPTIONS
242     if (__state_ == nullptr)
243         throw future_error(make_error_code(future_errc::no_state));
244 #endif
245     __state_->set_exception(__p);
246 }
247
248 void
249 promise<void>::set_value_at_thread_exit()
250 {
251 #ifndef _LIBCPP_NO_EXCEPTIONS
252     if (__state_ == nullptr)
253         throw future_error(make_error_code(future_errc::no_state));
254 #endif
255     __state_->set_value_at_thread_exit();
256 }
257
258 void
259 promise<void>::set_exception_at_thread_exit(exception_ptr __p)
260 {
261 #ifndef _LIBCPP_NO_EXCEPTIONS
262     if (__state_ == nullptr)
263         throw future_error(make_error_code(future_errc::no_state));
264 #endif
265     __state_->set_exception_at_thread_exit(__p);
266 }
267
268 shared_future<void>::~shared_future()
269 {
270     if (__state_)
271         __state_->__release_shared();
272 }
273
274 shared_future<void>&
275 shared_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
285 _LIBCPP_END_NAMESPACE_STD