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