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