blob: c67dc58826e866ed06021bd252eefcfa6a937cb8 [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
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 Hinnant1e15fd12011-05-26 19:48:01 +000019 virtual const char* name() const _NOEXCEPT;
Howard Hinnanta6521722010-08-25 17:32:05 +000020 virtual string message(int ev) const;
21};
22
23const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +000024__future_error_category::name() const _NOEXCEPT
Howard Hinnanta6521722010-08-25 17:32:05 +000025{
26 return "future";
27}
28
Logan Chien8f48c232013-12-14 06:45:09 +000029#if defined(__clang__)
Howard Hinnantcd942f12013-09-14 18:20:10 +000030#pragma clang diagnostic push
31#pragma clang diagnostic ignored "-Wswitch"
Logan Chien8f48c232013-12-14 06:45:09 +000032#elif defined(__GNUC__) || defined(__GNUG__)
33#pragma GCC diagnostic push
34#pragma GCC diagnostic ignored "-Wswitch"
35#endif
Howard Hinnantcd942f12013-09-14 18:20:10 +000036
Howard Hinnanta6521722010-08-25 17:32:05 +000037string
38__future_error_category::message(int ev) const
39{
Howard Hinnantb1bc0c42012-02-02 20:31:36 +000040 switch (static_cast<future_errc>(ev))
Howard Hinnanta6521722010-08-25 17:32:05 +000041 {
Howard Hinnantcd942f12013-09-14 18:20:10 +000042 case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)
Howard Hinnanta6521722010-08-25 17:32:05 +000043 case future_errc::broken_promise:
44 return string("The associated promise has been destructed prior "
45 "to the associated state becoming ready.");
46 case future_errc::future_already_retrieved:
47 return string("The future has already been retrieved from "
48 "the promise or packaged_task.");
49 case future_errc::promise_already_satisfied:
50 return string("The state of the promise has already been set.");
51 case future_errc::no_state:
52 return string("Operation not permitted on an object without "
53 "an associated state.");
54 }
55 return string("unspecified future_errc value\n");
56}
57
Logan Chien8f48c232013-12-14 06:45:09 +000058#if defined(__clang__)
Howard Hinnantcd942f12013-09-14 18:20:10 +000059#pragma clang diagnostic pop
Logan Chien8f48c232013-12-14 06:45:09 +000060#elif defined(__GNUC__) || defined(__GNUG__)
61#pragma GCC diagnostic pop
62#endif
Howard Hinnantcd942f12013-09-14 18:20:10 +000063
Howard Hinnanta6521722010-08-25 17:32:05 +000064const error_category&
Howard Hinnant8bf01dd2012-07-21 17:46:55 +000065future_category() _NOEXCEPT
Howard Hinnanta6521722010-08-25 17:32:05 +000066{
67 static __future_error_category __f;
68 return __f;
69}
70
71future_error::future_error(error_code __ec)
72 : logic_error(__ec.message()),
73 __ec_(__ec)
74{
75}
76
Howard Hinnant043fe1d2011-07-08 00:04:40 +000077future_error::~future_error() _NOEXCEPT
78{
79}
80
Howard Hinnant47499b12010-08-27 20:10:19 +000081void
Howard Hinnant1694d232011-05-28 14:41:13 +000082__assoc_sub_state::__on_zero_shared() _NOEXCEPT
Howard Hinnant47499b12010-08-27 20:10:19 +000083{
84 delete this;
85}
86
87void
88__assoc_sub_state::set_value()
89{
90 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +000091#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +000092 if (__has_value())
93 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +000094#endif
Howard Hinnant47499b12010-08-27 20:10:19 +000095 __state_ |= __constructed | ready;
Howard Hinnant47499b12010-08-27 20:10:19 +000096 __cv_.notify_all();
Howard Hinnant1b031c92013-01-14 20:01:24 +000097 __lk.unlock();
Howard Hinnant47499b12010-08-27 20:10:19 +000098}
99
100void
101__assoc_sub_state::set_value_at_thread_exit()
102{
103 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000104#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000105 if (__has_value())
106 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000107#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000108 __state_ |= __constructed;
Howard Hinnant5306d682010-10-14 19:18:04 +0000109 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +0000110 __lk.unlock();
111}
112
113void
114__assoc_sub_state::set_exception(exception_ptr __p)
115{
116 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000117#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000118 if (__has_value())
119 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000120#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000121 __exception_ = __p;
122 __state_ |= ready;
123 __lk.unlock();
124 __cv_.notify_all();
125}
126
127void
128__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
129{
130 unique_lock<mutex> __lk(__mut_);
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000131#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000132 if (__has_value())
133 throw future_error(make_error_code(future_errc::promise_already_satisfied));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000134#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000135 __exception_ = __p;
Howard Hinnant5306d682010-10-14 19:18:04 +0000136 __thread_local_data()->__make_ready_at_thread_exit(this);
Howard Hinnant47499b12010-08-27 20:10:19 +0000137 __lk.unlock();
138}
139
140void
141__assoc_sub_state::__make_ready()
142{
143 unique_lock<mutex> __lk(__mut_);
144 __state_ |= ready;
145 __lk.unlock();
146 __cv_.notify_all();
147}
148
149void
150__assoc_sub_state::copy()
151{
152 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000153 __sub_wait(__lk);
Howard Hinnant47499b12010-08-27 20:10:19 +0000154 if (__exception_ != nullptr)
155 rethrow_exception(__exception_);
156}
157
158void
Howard Hinnant54da3382010-08-30 18:46:21 +0000159__assoc_sub_state::wait()
Howard Hinnant47499b12010-08-27 20:10:19 +0000160{
161 unique_lock<mutex> __lk(__mut_);
Howard Hinnant54da3382010-08-30 18:46:21 +0000162 __sub_wait(__lk);
163}
164
165void
166__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
167{
168 if (!__is_ready())
169 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000170 if (__state_ & static_cast<unsigned>(deferred))
Howard Hinnant54da3382010-08-30 18:46:21 +0000171 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000172 __state_ &= ~static_cast<unsigned>(deferred);
Howard Hinnant54da3382010-08-30 18:46:21 +0000173 __lk.unlock();
174 __execute();
175 }
176 else
177 while (!__is_ready())
178 __cv_.wait(__lk);
179 }
180}
181
182void
183__assoc_sub_state::__execute()
184{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000185#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant54da3382010-08-30 18:46:21 +0000186 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000187#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000188}
189
190future<void>::future(__assoc_sub_state* __state)
191 : __state_(__state)
192{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000193#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000194 if (__state_->__has_future_attached())
195 throw future_error(make_error_code(future_errc::future_already_retrieved));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000196#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000197 __state_->__add_shared();
Howard Hinnant54da3382010-08-30 18:46:21 +0000198 __state_->__set_future_attached();
Howard Hinnant47499b12010-08-27 20:10:19 +0000199}
200
201future<void>::~future()
202{
203 if (__state_)
204 __state_->__release_shared();
205}
206
207void
208future<void>::get()
209{
Howard Hinnant54da3382010-08-30 18:46:21 +0000210 unique_ptr<__shared_count, __release_shared_count> __(__state_);
Howard Hinnant47499b12010-08-27 20:10:19 +0000211 __assoc_sub_state* __s = __state_;
212 __state_ = nullptr;
Howard Hinnant54da3382010-08-30 18:46:21 +0000213 __s->copy();
Howard Hinnant47499b12010-08-27 20:10:19 +0000214}
215
216promise<void>::promise()
217 : __state_(new __assoc_sub_state)
218{
219}
220
221promise<void>::~promise()
222{
223 if (__state_)
224 {
225 if (!__state_->__has_value() && __state_->use_count() > 1)
226 __state_->set_exception(make_exception_ptr(
227 future_error(make_error_code(future_errc::broken_promise))
228 ));
229 __state_->__release_shared();
230 }
231}
232
233future<void>
234promise<void>::get_future()
235{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000236#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000237 if (__state_ == nullptr)
238 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000239#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000240 return future<void>(__state_);
241}
242
243void
244promise<void>::set_value()
245{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000246#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000247 if (__state_ == nullptr)
248 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000249#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000250 __state_->set_value();
251}
252
253void
254promise<void>::set_exception(exception_ptr __p)
255{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000256#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000257 if (__state_ == nullptr)
258 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000259#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000260 __state_->set_exception(__p);
261}
262
263void
264promise<void>::set_value_at_thread_exit()
265{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000266#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000267 if (__state_ == nullptr)
268 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000269#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000270 __state_->set_value_at_thread_exit();
271}
272
273void
274promise<void>::set_exception_at_thread_exit(exception_ptr __p)
275{
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000276#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant47499b12010-08-27 20:10:19 +0000277 if (__state_ == nullptr)
278 throw future_error(make_error_code(future_errc::no_state));
Howard Hinnant22ba71b2011-07-13 16:00:50 +0000279#endif
Howard Hinnant47499b12010-08-27 20:10:19 +0000280 __state_->set_exception_at_thread_exit(__p);
281}
282
Howard Hinnant99be8232010-09-03 18:39:25 +0000283shared_future<void>::~shared_future()
284{
285 if (__state_)
286 __state_->__release_shared();
287}
288
289shared_future<void>&
290shared_future<void>::operator=(const shared_future& __rhs)
291{
292 if (__rhs.__state_)
293 __rhs.__state_->__add_shared();
294 if (__state_)
295 __state_->__release_shared();
296 __state_ = __rhs.__state_;
297 return *this;
298}
299
Howard Hinnanta6521722010-08-25 17:32:05 +0000300_LIBCPP_END_NAMESPACE_STD