blob: 0c5c2c4488d2d0575120c7f59273d12ec61caf40 [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();
Howard Hinnant1b031c92013-01-14 20:01:24 +0000101 __lk.unlock();
Howard Hinnant47499b12010-08-27 20:10:19 +0000102}
103
104void
105__assoc_sub_state::set_value_at_thread_exit()
106{
107 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000108#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000109 if (__has_value())
110 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000111#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000112 __state_ |= __constructed;
Howard Hinnant5306d682010-10-14 19:18:04 +0000113 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +0000114 __lk.unlock();
115}
116
117void
118__assoc_sub_state::set_exception(exception_ptr __p)
119{
120 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000121#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000122 if (__has_value())
123 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000124#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000125 __exception_ = __p;
126 __state_ |= ready;
127 __lk.unlock();
128 __cv_.notify_all();
129}
130
131void
132__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
133{
134 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000135#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000136 if (__has_value())
137 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000138#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000139 __exception_ = __p;
Howard Hinnant5306d682010-10-14 19:18:04 +0000140 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +0000141 __lk.unlock();
142}
143
144void
145__assoc_sub_state::__make_ready()
146{
147 unique_lock<mutex> __lk(__mut_);
148 __state_ |= ready;
149 __lk.unlock();
150 __cv_.notify_all();
151}
152
153void
154__assoc_sub_state::copy()
155{
156 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000157 __sub_wait(__lk);
Howard Hinnant47499b12010-08-27 20:10:19 +0000158 if (__exception_ != nullptr)
159 rethrow_exception(__exception_);
160}
161
162void
Howard Hinnant54da3382010-08-30 18:46:21 +0000163__assoc_sub_state::wait()
Howard Hinnant47499b12010-08-27 20:10:19 +0000164{
165 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000166 __sub_wait(__lk);
167}
168
169void
170__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
171{
172 if (!__is_ready())
173 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000174 if (__state_ & static_cast<unsigned>(deferred))
Howard Hinnant54da3382010-08-30 18:46:21 +0000175 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000176 __state_ &= ~static_cast<unsigned>(deferred);
Howard Hinnant54da3382010-08-30 18:46:21 +0000177 __lk.unlock();
178 __execute();
179 }
180 else
181 while (!__is_ready())
182 __cv_.wait(__lk);
183 }
184}
185
186void
187__assoc_sub_state::__execute()
188{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000189#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant54da3382010-08-30 18:46:21 +0000190 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000191#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000192}
193
194future<void>::future(__assoc_sub_state* __state)
195 : __state_(__state)
196{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000197#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000198 if (__state_->__has_future_attached())
199 throw future_error(make_error_code(future_errc::future_already_retrieved));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000200#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000201 __state_->__add_shared();
Howard Hinnant54da3382010-08-30 18:46:21 +0000202 __state_->__set_future_attached();
Howard Hinnant47499b12010-08-27 20:10:19 +0000203}
204
205future<void>::~future()
206{
207 if (__state_)
208 __state_->__release_shared();
209}
210
211void
212future<void>::get()
213{
Howard Hinnant54da3382010-08-30 18:46:21 +0000214 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant47499b12010-08-27 20:10:19 +0000215 __assoc_sub_state* __s = __state_;
216 __state_ = nullptr;
Howard Hinnant54da3382010-08-30 18:46:21 +0000217 __s->copy();
Howard Hinnant47499b12010-08-27 20:10:19 +0000218}
219
220promise<void>::promise()
221 : __state_(new __assoc_sub_state)
222{
223}
224
225promise<void>::~promise()
226{
227 if (__state_)
228 {
229 if (!__state_->__has_value() && __state_->use_count() > 1)
230 __state_->set_exception(make_exception_ptr(
231 future_error(make_error_code(future_errc::broken_promise))
232 ));
233 __state_->__release_shared();
234 }
235}
236
237future<void>
238promise<void>::get_future()
239{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000240#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000241 if (__state_ == nullptr)
242 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000243#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000244 return future<void>(__state_);
245}
246
247void
248promise<void>::set_value()
249{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000250#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000251 if (__state_ == nullptr)
252 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000253#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000254 __state_->set_value();
255}
256
257void
258promise<void>::set_exception(exception_ptr __p)
259{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000260#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000261 if (__state_ == nullptr)
262 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000263#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000264 __state_->set_exception(__p);
265}
266
267void
268promise<void>::set_value_at_thread_exit()
269{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000270#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000271 if (__state_ == nullptr)
272 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000273#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000274 __state_->set_value_at_thread_exit();
275}
276
277void
278promise<void>::set_exception_at_thread_exit(exception_ptr __p)
279{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000280#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000281 if (__state_ == nullptr)
282 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000283#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000284 __state_->set_exception_at_thread_exit(__p);
285}
286
Howard Hinnant99be8232010-09-03 18:39:25 +0000287shared_future<void>::~shared_future()
288{
289 if (__state_)
290 __state_->__release_shared();
291}
292
293shared_future<void>&
294shared_future<void>::operator=(const shared_future& __rhs)
295{
296 if (__rhs.__state_)
297 __rhs.__state_->__add_shared();
298 if (__state_)
299 __state_->__release_shared();
300 __state_ = __rhs.__state_;
301 return *this;
302}
303
Howard Hinnanta6521722010-08-25 17:32:05 +0000304_LIBCPP_END_NAMESPACE_STD
Jonathan Roelofs8d86b2e2014-09-05 19:45:05 +0000305
306#endif // !_LIBCPP_HAS_NO_THREADS