Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/src/future.cpp
Line
Count
Source (jump to first uncovered line)
1
//===----------------------------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include <__config>
10
11
#ifndef _LIBCPP_HAS_NO_THREADS
12
13
#include <future>
14
#include <string>
15
16
_LIBCPP_BEGIN_NAMESPACE_STD
17
18
class _LIBCPP_HIDDEN __future_error_category
19
    : public __do_message
20
{
21
public:
22
    virtual const char* name() const noexcept;
23
    virtual string message(int ev) const;
24
};
25
26
const char*
27
__future_error_category::name() const noexcept
28
0
{
29
0
    return "future";
30
0
}
31
32
_LIBCPP_DIAGNOSTIC_PUSH
33
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")
34
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")
35
36
string
37
__future_error_category::message(int ev) const
38
0
{
39
0
    switch (static_cast<future_errc>(ev))
40
0
    {
41
0
    case future_errc(0):  // For backwards compatibility with C++11 (LWG 2056)
42
0
    case future_errc::broken_promise:
43
0
        return string("The associated promise has been destructed prior "
44
0
                      "to the associated state becoming ready.");
45
0
    case future_errc::future_already_retrieved:
46
0
        return string("The future has already been retrieved from "
47
0
                      "the promise or packaged_task.");
48
0
    case future_errc::promise_already_satisfied:
49
0
        return string("The state of the promise has already been set.");
50
0
    case future_errc::no_state:
51
0
        return string("Operation not permitted on an object without "
52
0
                      "an associated state.");
53
0
    }
54
0
    return string("unspecified future_errc value\n");
55
0
}
56
57
_LIBCPP_DIAGNOSTIC_POP
58
59
const error_category&
60
future_category() noexcept
61
0
{
62
0
    static __future_error_category __f;
63
0
    return __f;
64
0
}
65
66
future_error::future_error(error_code __ec)
67
    : logic_error(__ec.message()),
68
      __ec_(__ec)
69
0
{
70
0
}
71
72
future_error::~future_error() noexcept
73
0
{
74
0
}
75
76
void
77
__assoc_sub_state::__on_zero_shared() noexcept
78
103
{
79
103
    delete this;
80
103
}
81
82
void
83
__assoc_sub_state::set_value()
84
103
{
85
103
    unique_lock<mutex> __lk(__mut_);
86
103
    if (__has_value())
87
0
        __throw_future_error(future_errc::promise_already_satisfied);
88
103
    __state_ |= __constructed | ready;
89
103
    __cv_.notify_all();
90
103
}
91
92
void
93
__assoc_sub_state::set_value_at_thread_exit()
94
0
{
95
0
    unique_lock<mutex> __lk(__mut_);
96
0
    if (__has_value())
97
0
        __throw_future_error(future_errc::promise_already_satisfied);
98
0
    __state_ |= __constructed;
99
0
    __thread_local_data()->__make_ready_at_thread_exit(this);
100
0
}
101
102
void
103
__assoc_sub_state::set_exception(exception_ptr __p)
104
0
{
105
0
    unique_lock<mutex> __lk(__mut_);
106
0
    if (__has_value())
107
0
        __throw_future_error(future_errc::promise_already_satisfied);
108
0
    __exception_ = __p;
109
0
    __state_ |= ready;
110
0
    __cv_.notify_all();
111
0
}
112
113
void
114
__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
115
0
{
116
0
    unique_lock<mutex> __lk(__mut_);
117
0
    if (__has_value())
118
0
        __throw_future_error(future_errc::promise_already_satisfied);
119
0
    __exception_ = __p;
120
0
    __thread_local_data()->__make_ready_at_thread_exit(this);
121
0
}
122
123
void
124
__assoc_sub_state::__make_ready()
125
0
{
126
0
    unique_lock<mutex> __lk(__mut_);
127
0
    __state_ |= ready;
128
0
    __cv_.notify_all();
129
0
}
130
131
void
132
__assoc_sub_state::copy()
133
0
{
134
0
    unique_lock<mutex> __lk(__mut_);
135
0
    __sub_wait(__lk);
136
0
    if (__exception_ != nullptr)
137
0
        rethrow_exception(__exception_);
138
0
}
139
140
void
141
__assoc_sub_state::wait()
142
0
{
143
0
    unique_lock<mutex> __lk(__mut_);
144
0
    __sub_wait(__lk);
145
0
}
146
147
void
148
__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
149
8
{
150
8
    if (!__is_ready())
151
0
    {
152
0
        if (__state_ & static_cast<unsigned>(deferred))
153
0
        {
154
0
            __state_ &= ~static_cast<unsigned>(deferred);
155
0
            __lk.unlock();
156
0
            __execute();
157
0
        }
158
0
        else
159
0
            while (!__is_ready())
160
0
                __cv_.wait(__lk);
161
0
    }
162
8
}
163
164
void
165
__assoc_sub_state::__execute()
166
0
{
167
0
    __throw_future_error(future_errc::no_state);
168
0
}
169
170
future<void>::future(__assoc_sub_state* __state)
171
    : __state_(__state)
172
103
{
173
103
    __state_->__attach_future();
174
103
}
175
176
future<void>::~future()
177
206
{
178
206
    if (__state_)
179
0
        __state_->__release_shared();
180
206
}
181
182
void
183
future<void>::get()
184
0
{
185
0
    unique_ptr<__shared_count, __release_shared_count> __(__state_);
186
0
    __assoc_sub_state* __s = __state_;
187
0
    __state_ = nullptr;
188
0
    __s->copy();
189
0
}
190
191
promise<void>::promise()
192
    : __state_(new __assoc_sub_state)
193
103
{
194
103
}
195
196
promise<void>::~promise()
197
103
{
198
103
    if (__state_)
199
103
    {
200
103
#ifndef _LIBCPP_NO_EXCEPTIONS
201
103
        if (!__state_->__has_value() && 
__state_->use_count() > 10
)
202
0
            __state_->set_exception(make_exception_ptr(
203
0
                      future_error(make_error_code(future_errc::broken_promise))
204
0
                                                      ));
205
103
#endif // _LIBCPP_NO_EXCEPTIONS
206
103
        __state_->__release_shared();
207
103
    }
208
103
}
209
210
future<void>
211
promise<void>::get_future()
212
103
{
213
103
    if (__state_ == nullptr)
214
0
        __throw_future_error(future_errc::no_state);
215
103
    return future<void>(__state_);
216
103
}
217
218
void
219
promise<void>::set_value()
220
103
{
221
103
    if (__state_ == nullptr)
222
0
        __throw_future_error(future_errc::no_state);
223
103
    __state_->set_value();
224
103
}
225
226
void
227
promise<void>::set_exception(exception_ptr __p)
228
0
{
229
0
    if (__state_ == nullptr)
230
0
        __throw_future_error(future_errc::no_state);
231
0
    __state_->set_exception(__p);
232
0
}
233
234
void
235
promise<void>::set_value_at_thread_exit()
236
0
{
237
0
    if (__state_ == nullptr)
238
0
        __throw_future_error(future_errc::no_state);
239
0
    __state_->set_value_at_thread_exit();
240
0
}
241
242
void
243
promise<void>::set_exception_at_thread_exit(exception_ptr __p)
244
0
{
245
0
    if (__state_ == nullptr)
246
0
        __throw_future_error(future_errc::no_state);
247
0
    __state_->set_exception_at_thread_exit(__p);
248
0
}
249
250
shared_future<void>::~shared_future()
251
103
{
252
103
    if (__state_)
253
103
        __state_->__release_shared();
254
103
}
255
256
shared_future<void>&
257
shared_future<void>::operator=(const shared_future& __rhs)
258
0
{
259
0
    if (__rhs.__state_)
260
0
        __rhs.__state_->__add_shared();
261
0
    if (__state_)
262
0
        __state_->__release_shared();
263
0
    __state_ = __rhs.__state_;
264
0
    return *this;
265
0
}
266
267
_LIBCPP_END_NAMESPACE_STD
268
269
#endif // !_LIBCPP_HAS_NO_THREADS