• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #if !_LIBCPP_SINGLE_THREADED
14 
15 _LIBCPP_BEGIN_NAMESPACE_STD
16 
17 class _LIBCPP_HIDDEN __future_error_category
18     : public __do_message
19 {
20 public:
21     virtual const char* name() const _NOEXCEPT;
22     virtual string message(int ev) const;
23 };
24 
25 const char*
name() const26 __future_error_category::name() const _NOEXCEPT
27 {
28     return "future";
29 }
30 
31 #if defined(__clang__)
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wswitch"
34 #elif defined(__GNUC__) || defined(__GNUG__)
35 #pragma GCC diagnostic push
36 #pragma GCC diagnostic ignored "-Wswitch"
37 #endif
38 
39 string
message(int ev) const40 __future_error_category::message(int ev) const
41 {
42     switch (static_cast<future_errc>(ev))
43     {
44     case future_errc(0):  // For backwards compatibility with C++11 (LWG 2056)
45     case future_errc::broken_promise:
46         return string("The associated promise has been destructed prior "
47                       "to the associated state becoming ready.");
48     case future_errc::future_already_retrieved:
49         return string("The future has already been retrieved from "
50                       "the promise or packaged_task.");
51     case future_errc::promise_already_satisfied:
52         return string("The state of the promise has already been set.");
53     case future_errc::no_state:
54         return string("Operation not permitted on an object without "
55                       "an associated state.");
56     }
57     return string("unspecified future_errc value\n");
58 }
59 
60 #if defined(__clang__)
61 #pragma clang diagnostic pop
62 #elif defined(__GNUC__) || defined(__GNUG__)
63 #pragma GCC diagnostic pop
64 #endif
65 
66 const error_category&
future_category()67 future_category() _NOEXCEPT
68 {
69     static __future_error_category __f;
70     return __f;
71 }
72 
future_error(error_code __ec)73 future_error::future_error(error_code __ec)
74     : logic_error(__ec.message()),
75       __ec_(__ec)
76 {
77 }
78 
~future_error()79 future_error::~future_error() _NOEXCEPT
80 {
81 }
82 
83 void
__on_zero_shared()84 __assoc_sub_state::__on_zero_shared() _NOEXCEPT
85 {
86     delete this;
87 }
88 
89 void
set_value()90 __assoc_sub_state::set_value()
91 {
92     unique_lock<mutex> __lk(__mut_);
93 #ifndef _LIBCPP_NO_EXCEPTIONS
94     if (__has_value())
95         throw future_error(make_error_code(future_errc::promise_already_satisfied));
96 #endif
97     __state_ |= __constructed | ready;
98     __cv_.notify_all();
99     __lk.unlock();
100 }
101 
102 void
set_value_at_thread_exit()103 __assoc_sub_state::set_value_at_thread_exit()
104 {
105     unique_lock<mutex> __lk(__mut_);
106 #ifndef _LIBCPP_NO_EXCEPTIONS
107     if (__has_value())
108         throw future_error(make_error_code(future_errc::promise_already_satisfied));
109 #endif
110     __state_ |= __constructed;
111     __thread_local_data()->__make_ready_at_thread_exit(this);
112     __lk.unlock();
113 }
114 
115 void
set_exception(exception_ptr __p)116 __assoc_sub_state::set_exception(exception_ptr __p)
117 {
118     unique_lock<mutex> __lk(__mut_);
119 #ifndef _LIBCPP_NO_EXCEPTIONS
120     if (__has_value())
121         throw future_error(make_error_code(future_errc::promise_already_satisfied));
122 #endif
123     __exception_ = __p;
124     __state_ |= ready;
125     __lk.unlock();
126     __cv_.notify_all();
127 }
128 
129 void
set_exception_at_thread_exit(exception_ptr __p)130 __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
131 {
132     unique_lock<mutex> __lk(__mut_);
133 #ifndef _LIBCPP_NO_EXCEPTIONS
134     if (__has_value())
135         throw future_error(make_error_code(future_errc::promise_already_satisfied));
136 #endif
137     __exception_ = __p;
138     __thread_local_data()->__make_ready_at_thread_exit(this);
139     __lk.unlock();
140 }
141 
142 void
__make_ready()143 __assoc_sub_state::__make_ready()
144 {
145     unique_lock<mutex> __lk(__mut_);
146     __state_ |= ready;
147     __lk.unlock();
148     __cv_.notify_all();
149 }
150 
151 void
copy()152 __assoc_sub_state::copy()
153 {
154     unique_lock<mutex> __lk(__mut_);
155     __sub_wait(__lk);
156     if (__exception_ != nullptr)
157         rethrow_exception(__exception_);
158 }
159 
160 void
wait()161 __assoc_sub_state::wait()
162 {
163     unique_lock<mutex> __lk(__mut_);
164     __sub_wait(__lk);
165 }
166 
167 void
__sub_wait(unique_lock<mutex> & __lk)168 __assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
169 {
170     if (!__is_ready())
171     {
172         if (__state_ & static_cast<unsigned>(deferred))
173         {
174             __state_ &= ~static_cast<unsigned>(deferred);
175             __lk.unlock();
176             __execute();
177         }
178         else
179             while (!__is_ready())
180                 __cv_.wait(__lk);
181     }
182 }
183 
184 void
__execute()185 __assoc_sub_state::__execute()
186 {
187 #ifndef _LIBCPP_NO_EXCEPTIONS
188     throw future_error(make_error_code(future_errc::no_state));
189 #endif
190 }
191 
future(__assoc_sub_state * __state)192 future<void>::future(__assoc_sub_state* __state)
193     : __state_(__state)
194 {
195 #ifndef _LIBCPP_NO_EXCEPTIONS
196     if (__state_->__has_future_attached())
197         throw future_error(make_error_code(future_errc::future_already_retrieved));
198 #endif
199     __state_->__add_shared();
200     __state_->__set_future_attached();
201 }
202 
~future()203 future<void>::~future()
204 {
205     if (__state_)
206         __state_->__release_shared();
207 }
208 
209 void
get()210 future<void>::get()
211 {
212     unique_ptr<__shared_count, __release_shared_count> __(__state_);
213     __assoc_sub_state* __s = __state_;
214     __state_ = nullptr;
215     __s->copy();
216 }
217 
promise()218 promise<void>::promise()
219     : __state_(new __assoc_sub_state)
220 {
221 }
222 
~promise()223 promise<void>::~promise()
224 {
225     if (__state_)
226     {
227         if (!__state_->__has_value() && __state_->use_count() > 1)
228             __state_->set_exception(make_exception_ptr(
229                       future_error(make_error_code(future_errc::broken_promise))
230                                                       ));
231         __state_->__release_shared();
232     }
233 }
234 
235 future<void>
get_future()236 promise<void>::get_future()
237 {
238 #ifndef _LIBCPP_NO_EXCEPTIONS
239     if (__state_ == nullptr)
240         throw future_error(make_error_code(future_errc::no_state));
241 #endif
242     return future<void>(__state_);
243 }
244 
245 void
set_value()246 promise<void>::set_value()
247 {
248 #ifndef _LIBCPP_NO_EXCEPTIONS
249     if (__state_ == nullptr)
250         throw future_error(make_error_code(future_errc::no_state));
251 #endif
252     __state_->set_value();
253 }
254 
255 void
set_exception(exception_ptr __p)256 promise<void>::set_exception(exception_ptr __p)
257 {
258 #ifndef _LIBCPP_NO_EXCEPTIONS
259     if (__state_ == nullptr)
260         throw future_error(make_error_code(future_errc::no_state));
261 #endif
262     __state_->set_exception(__p);
263 }
264 
265 void
set_value_at_thread_exit()266 promise<void>::set_value_at_thread_exit()
267 {
268 #ifndef _LIBCPP_NO_EXCEPTIONS
269     if (__state_ == nullptr)
270         throw future_error(make_error_code(future_errc::no_state));
271 #endif
272     __state_->set_value_at_thread_exit();
273 }
274 
275 void
set_exception_at_thread_exit(exception_ptr __p)276 promise<void>::set_exception_at_thread_exit(exception_ptr __p)
277 {
278 #ifndef _LIBCPP_NO_EXCEPTIONS
279     if (__state_ == nullptr)
280         throw future_error(make_error_code(future_errc::no_state));
281 #endif
282     __state_->set_exception_at_thread_exit(__p);
283 }
284 
~shared_future()285 shared_future<void>::~shared_future()
286 {
287     if (__state_)
288         __state_->__release_shared();
289 }
290 
291 shared_future<void>&
operator =(const shared_future & __rhs)292 shared_future<void>::operator=(const shared_future& __rhs)
293 {
294     if (__rhs.__state_)
295         __rhs.__state_->__add_shared();
296     if (__state_)
297         __state_->__release_shared();
298     __state_ = __rhs.__state_;
299     return *this;
300 }
301 
302 _LIBCPP_END_NAMESPACE_STD
303 
304 #endif // !_LIBCPP_SINGLE_THREADED
305 
306 
307