blob: 82b9b60ee4e33b58b1897294e88953d1996b00f8 [file] [log] [blame]
Howard Hinnant96803d92010-08-25 17:32:05 +00001//===------------------------- 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 Hinnant3820f6b2010-08-27 20:10:19 +000063void
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_);
127 while (!__is_ready())
128 __cv_.wait(__lk);
129 if (__exception_ != nullptr)
130 rethrow_exception(__exception_);
131}
132
133void
134__assoc_sub_state::wait() const
135{
136 unique_lock<mutex> __lk(__mut_);
137 while (!__is_ready())
138 __cv_.wait(__lk);
139}
140
141future<void>::future(__assoc_sub_state* __state)
142 : __state_(__state)
143{
144 if (__state_->__has_future_attached())
145 throw future_error(make_error_code(future_errc::future_already_retrieved));
146 __state_->__add_shared();
147}
148
149future<void>::~future()
150{
151 if (__state_)
152 __state_->__release_shared();
153}
154
155void
156future<void>::get()
157{
158 __assoc_sub_state* __s = __state_;
159 __state_ = nullptr;
160 return __s->copy();
161}
162
163promise<void>::promise()
164 : __state_(new __assoc_sub_state)
165{
166}
167
168promise<void>::~promise()
169{
170 if (__state_)
171 {
172 if (!__state_->__has_value() && __state_->use_count() > 1)
173 __state_->set_exception(make_exception_ptr(
174 future_error(make_error_code(future_errc::broken_promise))
175 ));
176 __state_->__release_shared();
177 }
178}
179
180future<void>
181promise<void>::get_future()
182{
183 if (__state_ == nullptr)
184 throw future_error(make_error_code(future_errc::no_state));
185 return future<void>(__state_);
186}
187
188void
189promise<void>::set_value()
190{
191 if (__state_ == nullptr)
192 throw future_error(make_error_code(future_errc::no_state));
193 __state_->set_value();
194}
195
196void
197promise<void>::set_exception(exception_ptr __p)
198{
199 if (__state_ == nullptr)
200 throw future_error(make_error_code(future_errc::no_state));
201 __state_->set_exception(__p);
202}
203
204void
205promise<void>::set_value_at_thread_exit()
206{
207 if (__state_ == nullptr)
208 throw future_error(make_error_code(future_errc::no_state));
209 __state_->set_value_at_thread_exit();
210}
211
212void
213promise<void>::set_exception_at_thread_exit(exception_ptr __p)
214{
215 if (__state_ == nullptr)
216 throw future_error(make_error_code(future_errc::no_state));
217 __state_->set_exception_at_thread_exit(__p);
218}
219
Howard Hinnant96803d92010-08-25 17:32:05 +0000220_LIBCPP_END_NAMESPACE_STD