blob: 3132b1861af2bf8ac8d99a616f7d58203c660ba5 [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
Jonathan Roelofs8d86b2e2014-09-05 19:45:05 +000010#include "__config"
11
12#ifndef _LIBCPP_HAS_NO_THREADS
13
Howard Hinnanta6521722010-08-25 17:32:05 +000014#include "future"
15#include "string"
16
17_LIBCPP_BEGIN_NAMESPACE_STD
18
19class _LIBCPP_HIDDEN __future_error_category
20 : public __do_message
21{
22public:
Howard Hinnant1e15fd12011-05-26 19:48:01 +000023 virtual const char* name() const _NOEXCEPT;
Howard Hinnanta6521722010-08-25 17:32:05 +000024 virtual string message(int ev) const;
25};
26
27const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +000028__future_error_category::name() const _NOEXCEPT
Howard Hinnanta6521722010-08-25 17:32:05 +000029{
30 return "future";
31}
32
Logan Chien8f48c232013-12-14 06:45:09 +000033#if defined(__clang__)
Howard Hinnantcd942f12013-09-14 18:20:10 +000034#pragma clang diagnostic push
35#pragma clang diagnostic ignored "-Wswitch"
Logan Chien8f48c232013-12-14 06:45:09 +000036#elif defined(__GNUC__) || defined(__GNUG__)
37#pragma GCC diagnostic push
38#pragma GCC diagnostic ignored "-Wswitch"
39#endif
Howard Hinnantcd942f12013-09-14 18:20:10 +000040
Howard Hinnanta6521722010-08-25 17:32:05 +000041string
42__future_error_category::message(int ev) const
43{
Howard Hinnantb1bc0c42012-02-02 20:31:36 +000044 switch (static_cast<future_errc>(ev))
Howard Hinnanta6521722010-08-25 17:32:05 +000045 {
Howard Hinnantcd942f12013-09-14 18:20:10 +000046 case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)
Howard Hinnanta6521722010-08-25 17:32:05 +000047 case future_errc::broken_promise:
48 return string("The associated promise has been destructed prior "
49 "to the associated state becoming ready.");
50 case future_errc::future_already_retrieved:
51 return string("The future has already been retrieved from "
52 "the promise or packaged_task.");
53 case future_errc::promise_already_satisfied:
54 return string("The state of the promise has already been set.");
55 case future_errc::no_state:
56 return string("Operation not permitted on an object without "
57 "an associated state.");
58 }
59 return string("unspecified future_errc value\n");
60}
61
Logan Chien8f48c232013-12-14 06:45:09 +000062#if defined(__clang__)
Howard Hinnantcd942f12013-09-14 18:20:10 +000063#pragma clang diagnostic pop
Logan Chien8f48c232013-12-14 06:45:09 +000064#elif defined(__GNUC__) || defined(__GNUG__)
65#pragma GCC diagnostic pop
66#endif
Howard Hinnantcd942f12013-09-14 18:20:10 +000067
Howard Hinnanta6521722010-08-25 17:32:05 +000068const error_category&
Howard Hinnant8bf01dd2012-07-21 17:46:55 +000069future_category() _NOEXCEPT
Howard Hinnanta6521722010-08-25 17:32:05 +000070{
71 static __future_error_category __f;
72 return __f;
73}
74
75future_error::future_error(error_code __ec)
76 : logic_error(__ec.message()),
77 __ec_(__ec)
78{
79}
80
Howard Hinnant043fe1d2011-07-08 00:04:40 +000081future_error::~future_error() _NOEXCEPT
82{
83}
84
Howard Hinnant47499b12010-08-27 20:10:19 +000085void
Howard Hinnant1694d232011-05-28 14:41:13 +000086__assoc_sub_state::__on_zero_shared() _NOEXCEPT
Howard Hinnant47499b12010-08-27 20:10:19 +000087{
88 delete this;
89}
90
91void
92__assoc_sub_state::set_value()
93{
94 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +000095#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +000096 if (__has_value())
97 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +000098#endif
Howard Hinnant47499b12010-08-27 20:10:19 +000099 __state_ |= __constructed | ready;
Howard Hinnant47499b12010-08-27 20:10:19 +0000100 __cv_.notify_all();
101}
102
103void
104__assoc_sub_state::set_value_at_thread_exit()
105{
106 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000107#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000108 if (__has_value())
109 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000110#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000111 __state_ |= __constructed;
Howard Hinnant5306d682010-10-14 19:18:04 +0000112 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +0000113}
114
115void
116__assoc_sub_state::set_exception(exception_ptr __p)
117{
118 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000119#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000120 if (__has_value())
121 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000122#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000123 __exception_ = __p;
124 __state_ |= ready;
Howard Hinnant47499b12010-08-27 20:10:19 +0000125 __cv_.notify_all();
126}
127
128void
129__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
130{
131 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000132#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000133 if (__has_value())
134 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000135#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000136 __exception_ = __p;
Howard Hinnant5306d682010-10-14 19:18:04 +0000137 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +0000138}
139
140void
141__assoc_sub_state::__make_ready()
142{
143 unique_lock<mutex> __lk(__mut_);
144 __state_ |= ready;
Howard Hinnant47499b12010-08-27 20:10:19 +0000145 __cv_.notify_all();
146}
147
148void
149__assoc_sub_state::copy()
150{
151 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000152 __sub_wait(__lk);
Howard Hinnant47499b12010-08-27 20:10:19 +0000153 if (__exception_ != nullptr)
154 rethrow_exception(__exception_);
155}
156
157void
Howard Hinnant54da3382010-08-30 18:46:21 +0000158__assoc_sub_state::wait()
Howard Hinnant47499b12010-08-27 20:10:19 +0000159{
160 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000161 __sub_wait(__lk);
162}
163
164void
165__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
166{
167 if (!__is_ready())
168 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000169 if (__state_ & static_cast<unsigned>(deferred))
Howard Hinnant54da3382010-08-30 18:46:21 +0000170 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000171 __state_ &= ~static_cast<unsigned>(deferred);
Howard Hinnant54da3382010-08-30 18:46:21 +0000172 __lk.unlock();
173 __execute();
174 }
175 else
176 while (!__is_ready())
177 __cv_.wait(__lk);
178 }
179}
180
181void
182__assoc_sub_state::__execute()
183{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000184#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant54da3382010-08-30 18:46:21 +0000185 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000186#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000187}
188
189future<void>::future(__assoc_sub_state* __state)
190 : __state_(__state)
191{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000192#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000193 if (__state_->__has_future_attached())
194 throw future_error(make_error_code(future_errc::future_already_retrieved));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000195#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000196 __state_->__add_shared();
Howard Hinnant54da3382010-08-30 18:46:21 +0000197 __state_->__set_future_attached();
Howard Hinnant47499b12010-08-27 20:10:19 +0000198}
199
200future<void>::~future()
201{
202 if (__state_)
203 __state_->__release_shared();
204}
205
206void
207future<void>::get()
208{
Howard Hinnant54da3382010-08-30 18:46:21 +0000209 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant47499b12010-08-27 20:10:19 +0000210 __assoc_sub_state* __s = __state_;
211 __state_ = nullptr;
Howard Hinnant54da3382010-08-30 18:46:21 +0000212 __s->copy();
Howard Hinnant47499b12010-08-27 20:10:19 +0000213}
214
215promise<void>::promise()
216 : __state_(new __assoc_sub_state)
217{
218}
219
220promise<void>::~promise()
221{
222 if (__state_)
223 {
224 if (!__state_->__has_value() && __state_->use_count() > 1)
225 __state_->set_exception(make_exception_ptr(
226 future_error(make_error_code(future_errc::broken_promise))
227 ));
228 __state_->__release_shared();
229 }
230}
231
232future<void>
233promise<void>::get_future()
234{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000235#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000236 if (__state_ == nullptr)
237 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000238#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000239 return future<void>(__state_);
240}
241
242void
243promise<void>::set_value()
244{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000245#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000246 if (__state_ == nullptr)
247 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000248#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000249 __state_->set_value();
250}
251
252void
253promise<void>::set_exception(exception_ptr __p)
254{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000255#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000256 if (__state_ == nullptr)
257 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000258#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000259 __state_->set_exception(__p);
260}
261
262void
263promise<void>::set_value_at_thread_exit()
264{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000265#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000266 if (__state_ == nullptr)
267 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000268#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000269 __state_->set_value_at_thread_exit();
270}
271
272void
273promise<void>::set_exception_at_thread_exit(exception_ptr __p)
274{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000275#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000276 if (__state_ == nullptr)
277 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000278#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000279 __state_->set_exception_at_thread_exit(__p);
280}
281
Howard Hinnant99be8232010-09-03 18:39:25 +0000282shared_future<void>::~shared_future()
283{
284 if (__state_)
285 __state_->__release_shared();
286}
287
288shared_future<void>&
289shared_future<void>::operator=(const shared_future& __rhs)
290{
291 if (__rhs.__state_)
292 __rhs.__state_->__add_shared();
293 if (__state_)
294 __state_->__release_shared();
295 __state_ = __rhs.__state_;
296 return *this;
297}
298
Howard Hinnanta6521722010-08-25 17:32:05 +0000299_LIBCPP_END_NAMESPACE_STD
Jonathan Roelofs8d86b2e2014-09-05 19:45:05 +0000300
301#endif // !_LIBCPP_HAS_NO_THREADS