Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/include/__mutex_base
Line
Count
Source (jump to first uncovered line)
1
// -*- C++ -*-
2
//===----------------------------------------------------------------------===//
3
//
4
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5
// See https://llvm.org/LICENSE.txt for license information.
6
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
//
8
//===----------------------------------------------------------------------===//
9
10
#ifndef _LIBCPP___MUTEX_BASE
11
#define _LIBCPP___MUTEX_BASE
12
13
#include <__config>
14
#include <chrono>
15
#include <system_error>
16
#include <__threading_support>
17
18
#include <time.h>
19
20
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21
#pragma GCC system_header
22
#endif
23
24
_LIBCPP_PUSH_MACROS
25
#include <__undef_macros>
26
27
28
_LIBCPP_BEGIN_NAMESPACE_STD
29
30
#ifndef _LIBCPP_HAS_NO_THREADS
31
32
class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
33
{
34
    __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
35
36
public:
37
    _LIBCPP_INLINE_VISIBILITY
38
1.21M
    _LIBCPP_CONSTEXPR mutex() = default;
39
40
    mutex(const mutex&) = delete;
41
    mutex& operator=(const mutex&) = delete;
42
43
#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION)
44
    ~mutex() = default;
45
#else
46
    ~mutex() _NOEXCEPT;
47
#endif
48
49
    void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
50
    bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
51
    void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
52
53
    typedef __libcpp_mutex_t* native_handle_type;
54
150
    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
55
};
56
57
static_assert(is_nothrow_default_constructible<mutex>::value,
58
              "the default constructor for std::mutex must be nothrow");
59
60
struct _LIBCPP_TYPE_VIS defer_lock_t { explicit defer_lock_t() = default; };
61
struct _LIBCPP_TYPE_VIS try_to_lock_t { explicit try_to_lock_t() = default; };
62
struct _LIBCPP_TYPE_VIS adopt_lock_t { explicit adopt_lock_t() = default; };
63
64
#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
65
66
extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t  defer_lock;
67
extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock;
68
extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t  adopt_lock;
69
70
#else
71
72
/* _LIBCPP_INLINE_VAR */ constexpr defer_lock_t  defer_lock  = defer_lock_t();
73
/* _LIBCPP_INLINE_VAR */ constexpr try_to_lock_t try_to_lock = try_to_lock_t();
74
/* _LIBCPP_INLINE_VAR */ constexpr adopt_lock_t  adopt_lock  = adopt_lock_t();
75
76
#endif
77
78
template <class _Mutex>
79
class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
80
lock_guard
81
{
82
public:
83
    typedef _Mutex mutex_type;
84
85
private:
86
    mutex_type& __m_;
87
public:
88
89
    _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY
90
    explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
91
5.92M
        : __m_(__m) {__m_.lock();}
92
93
    _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY
94
    lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
95
        : __m_(__m) {}
96
    _LIBCPP_INLINE_VISIBILITY
97
5.94M
    ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
98
99
private:
100
    lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE;
101
    lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE;
102
};
103
104
template <class _Mutex>
105
class _LIBCPP_TEMPLATE_VIS unique_lock
106
{
107
public:
108
    typedef _Mutex mutex_type;
109
110
private:
111
    mutex_type* __m_;
112
    bool __owns_;
113
114
public:
115
    _LIBCPP_INLINE_VISIBILITY
116
    unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
117
    _LIBCPP_INLINE_VISIBILITY
118
    explicit unique_lock(mutex_type& __m)
119
1.56M
        : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();}
120
    _LIBCPP_INLINE_VISIBILITY
121
    unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
122
        : __m_(_VSTD::addressof(__m)), __owns_(false) {}
123
    _LIBCPP_INLINE_VISIBILITY
124
    unique_lock(mutex_type& __m, try_to_lock_t)
125
0
        : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {}
126
    _LIBCPP_INLINE_VISIBILITY
127
    unique_lock(mutex_type& __m, adopt_lock_t)
128
        : __m_(_VSTD::addressof(__m)), __owns_(true) {}
129
    template <class _Clock, class _Duration>
130
    _LIBCPP_INLINE_VISIBILITY
131
        unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
132
            : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
133
    template <class _Rep, class _Period>
134
    _LIBCPP_INLINE_VISIBILITY
135
        unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
136
            : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
137
    _LIBCPP_INLINE_VISIBILITY
138
    ~unique_lock()
139
1.67M
    {
140
1.67M
        if (__owns_)
141
1.41M
            __m_->unlock();
142
1.67M
    }
143
144
private:
145
    unique_lock(unique_lock const&); // = delete;
146
    unique_lock& operator=(unique_lock const&); // = delete;
147
148
public:
149
#ifndef _LIBCPP_CXX03_LANG
150
    _LIBCPP_INLINE_VISIBILITY
151
    unique_lock(unique_lock&& __u) _NOEXCEPT
152
        : __m_(__u.__m_), __owns_(__u.__owns_)
153
        {__u.__m_ = nullptr; __u.__owns_ = false;}
154
    _LIBCPP_INLINE_VISIBILITY
155
    unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
156
        {
157
            if (__owns_)
158
                __m_->unlock();
159
            __m_ = __u.__m_;
160
            __owns_ = __u.__owns_;
161
            __u.__m_ = nullptr;
162
            __u.__owns_ = false;
163
            return *this;
164
        }
165
166
#endif  // _LIBCPP_CXX03_LANG
167
168
    void lock();
169
    bool try_lock();
170
171
    template <class _Rep, class _Period>
172
        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
173
    template <class _Clock, class _Duration>
174
        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
175
176
    void unlock();
177
178
    _LIBCPP_INLINE_VISIBILITY
179
    void swap(unique_lock& __u) _NOEXCEPT
180
    {
181
        _VSTD::swap(__m_, __u.__m_);
182
        _VSTD::swap(__owns_, __u.__owns_);
183
    }
184
    _LIBCPP_INLINE_VISIBILITY
185
    mutex_type* release() _NOEXCEPT
186
9.91k
    {
187
9.91k
        mutex_type* __m = __m_;
188
9.91k
        __m_ = nullptr;
189
9.91k
        __owns_ = false;
190
9.91k
        return __m;
191
9.91k
    }
192
193
    _LIBCPP_INLINE_VISIBILITY
194
150
    bool owns_lock() const _NOEXCEPT {return __owns_;}
195
    _LIBCPP_INLINE_VISIBILITY
196
    _LIBCPP_EXPLICIT
197
        operator bool () const _NOEXCEPT {return __owns_;}
198
    _LIBCPP_INLINE_VISIBILITY
199
150
    mutex_type* mutex() const _NOEXCEPT {return __m_;}
200
};
201
202
template <class _Mutex>
203
void
204
unique_lock<_Mutex>::lock()
205
{
206
    if (__m_ == nullptr)
207
        __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
208
    if (__owns_)
209
        __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
210
    __m_->lock();
211
    __owns_ = true;
212
}
213
214
template <class _Mutex>
215
bool
216
unique_lock<_Mutex>::try_lock()
217
{
218
    if (__m_ == nullptr)
219
        __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
220
    if (__owns_)
221
        __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
222
    __owns_ = __m_->try_lock();
223
    return __owns_;
224
}
225
226
template <class _Mutex>
227
template <class _Rep, class _Period>
228
bool
229
unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
230
{
231
    if (__m_ == nullptr)
232
        __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
233
    if (__owns_)
234
        __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
235
    __owns_ = __m_->try_lock_for(__d);
236
    return __owns_;
237
}
238
239
template <class _Mutex>
240
template <class _Clock, class _Duration>
241
bool
242
unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
243
{
244
    if (__m_ == nullptr)
245
        __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
246
    if (__owns_)
247
        __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
248
    __owns_ = __m_->try_lock_until(__t);
249
    return __owns_;
250
}
251
252
template <class _Mutex>
253
void
254
unique_lock<_Mutex>::unlock()
255
147k
{
256
147k
    if (!__owns_)
257
0
        __throw_system_error(EPERM, "unique_lock::unlock: not locked");
258
147k
    __m_->unlock();
259
147k
    __owns_ = false;
260
147k
}
261
262
template <class _Mutex>
263
inline _LIBCPP_INLINE_VISIBILITY
264
void
265
swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
266
    {__x.swap(__y);}
267
268
//enum class cv_status
269
_LIBCPP_DECLARE_STRONG_ENUM(cv_status)
270
{
271
    no_timeout,
272
    timeout
273
};
274
_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
275
276
class _LIBCPP_TYPE_VIS condition_variable
277
{
278
    __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
279
public:
280
    _LIBCPP_INLINE_VISIBILITY
281
99.2k
    _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
282
283
#ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
284
    ~condition_variable() = default;
285
#else
286
    ~condition_variable();
287
#endif
288
289
    condition_variable(const condition_variable&) = delete;
290
    condition_variable& operator=(const condition_variable&) = delete;
291
292
    void notify_one() _NOEXCEPT;
293
    void notify_all() _NOEXCEPT;
294
295
    void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
296
    template <class _Predicate>
297
        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
298
        void wait(unique_lock<mutex>& __lk, _Predicate __pred);
299
300
    template <class _Clock, class _Duration>
301
        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
302
        cv_status
303
        wait_until(unique_lock<mutex>& __lk,
304
                   const chrono::time_point<_Clock, _Duration>& __t);
305
306
    template <class _Clock, class _Duration, class _Predicate>
307
        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
308
        bool
309
        wait_until(unique_lock<mutex>& __lk,
310
                   const chrono::time_point<_Clock, _Duration>& __t,
311
                   _Predicate __pred);
312
313
    template <class _Rep, class _Period>
314
        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
315
        cv_status
316
        wait_for(unique_lock<mutex>& __lk,
317
                 const chrono::duration<_Rep, _Period>& __d);
318
319
    template <class _Rep, class _Period, class _Predicate>
320
        bool
321
        _LIBCPP_INLINE_VISIBILITY
322
        wait_for(unique_lock<mutex>& __lk,
323
                 const chrono::duration<_Rep, _Period>& __d,
324
                 _Predicate __pred);
325
326
    typedef __libcpp_condvar_t* native_handle_type;
327
0
    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
328
329
private:
330
    void __do_timed_wait(unique_lock<mutex>& __lk,
331
       chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
332
#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
333
    void __do_timed_wait(unique_lock<mutex>& __lk,
334
       chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT;
335
#endif
336
    template <class _Clock>
337
    void __do_timed_wait(unique_lock<mutex>& __lk,
338
       chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT;
339
};
340
#endif // !_LIBCPP_HAS_NO_THREADS
341
342
template <class _Rep, class _Period>
343
inline _LIBCPP_INLINE_VISIBILITY
344
typename enable_if
345
<
346
    is_floating_point<_Rep>::value,
347
    chrono::nanoseconds
348
>::type
349
__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d)
350
{
351
    using namespace chrono;
352
    using __ratio = ratio_divide<_Period, nano>;
353
    using __ns_rep = nanoseconds::rep;
354
    _Rep __result_float = __d.count() * __ratio::num / __ratio::den;
355
356
    _Rep __result_max = numeric_limits<__ns_rep>::max();
357
    if (__result_float >= __result_max) {
358
        return nanoseconds::max();
359
    }
360
361
    _Rep __result_min = numeric_limits<__ns_rep>::min();
362
    if (__result_float <= __result_min) {
363
        return nanoseconds::min();
364
    }
365
366
    return nanoseconds(static_cast<__ns_rep>(__result_float));
367
}
368
369
template <class _Rep, class _Period>
370
inline _LIBCPP_INLINE_VISIBILITY
371
typename enable_if
372
<
373
    !is_floating_point<_Rep>::value,
374
    chrono::nanoseconds
375
>::type
376
__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d)
377
{
378
    using namespace chrono;
379
    if (__d.count() == 0) {
380
        return nanoseconds(0);
381
    }
382
383
    using __ratio = ratio_divide<_Period, nano>;
384
    using __ns_rep = nanoseconds::rep;
385
    __ns_rep __result_max = std::numeric_limits<__ns_rep>::max();
386
    if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) {
387
        return nanoseconds::max();
388
    }
389
390
    __ns_rep __result_min = std::numeric_limits<__ns_rep>::min();
391
    if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) {
392
        return nanoseconds::min();
393
    }
394
395
    __ns_rep __result = __d.count() * __ratio::num / __ratio::den;
396
    if (__result == 0) {
397
        return nanoseconds(1);
398
    }
399
400
    return nanoseconds(__result);
401
}
402
403
#ifndef _LIBCPP_HAS_NO_THREADS
404
template <class _Predicate>
405
void
406
condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
407
{
408
    while (!__pred())
409
        wait(__lk);
410
}
411
412
template <class _Clock, class _Duration>
413
cv_status
414
condition_variable::wait_until(unique_lock<mutex>& __lk,
415
                               const chrono::time_point<_Clock, _Duration>& __t)
416
{
417
    using namespace chrono;
418
    using __clock_tp_ns = time_point<_Clock, nanoseconds>;
419
420
    typename _Clock::time_point __now = _Clock::now();
421
    if (__t <= __now)
422
        return cv_status::timeout;
423
424
    __clock_tp_ns __t_ns = __clock_tp_ns(__safe_nanosecond_cast(__t.time_since_epoch()));
425
426
    __do_timed_wait(__lk, __t_ns);
427
    return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
428
}
429
430
template <class _Clock, class _Duration, class _Predicate>
431
bool
432
condition_variable::wait_until(unique_lock<mutex>& __lk,
433
                   const chrono::time_point<_Clock, _Duration>& __t,
434
                   _Predicate __pred)
435
{
436
    while (!__pred())
437
    {
438
        if (wait_until(__lk, __t) == cv_status::timeout)
439
            return __pred();
440
    }
441
    return true;
442
}
443
444
template <class _Rep, class _Period>
445
cv_status
446
condition_variable::wait_for(unique_lock<mutex>& __lk,
447
                             const chrono::duration<_Rep, _Period>& __d)
448
{
449
    using namespace chrono;
450
    if (__d <= __d.zero())
451
        return cv_status::timeout;
452
    using __ns_rep = nanoseconds::rep;
453
    steady_clock::time_point __c_now = steady_clock::now();
454
455
#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
456
    using __clock_tp_ns = time_point<steady_clock, nanoseconds>;
457
    __ns_rep __now_count_ns = __safe_nanosecond_cast(__c_now.time_since_epoch()).count();
458
#else
459
    using __clock_tp_ns = time_point<system_clock, nanoseconds>;
460
    __ns_rep __now_count_ns = __safe_nanosecond_cast(system_clock::now().time_since_epoch()).count();
461
#endif
462
463
    __ns_rep __d_ns_count = __safe_nanosecond_cast(__d).count();
464
465
    if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) {
466
        __do_timed_wait(__lk, __clock_tp_ns::max());
467
    } else {
468
        __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count)));
469
    }
470
471
    return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
472
                                                 cv_status::timeout;
473
}
474
475
template <class _Rep, class _Period, class _Predicate>
476
inline
477
bool
478
condition_variable::wait_for(unique_lock<mutex>& __lk,
479
                             const chrono::duration<_Rep, _Period>& __d,
480
                             _Predicate __pred)
481
{
482
    return wait_until(__lk, chrono::steady_clock::now() + __d,
483
                      _VSTD::move(__pred));
484
}
485
486
#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
487
inline
488
void
489
condition_variable::__do_timed_wait(unique_lock<mutex>& __lk,
490
     chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT
491
{
492
    using namespace chrono;
493
    if (!__lk.owns_lock())
494
        __throw_system_error(EPERM,
495
                            "condition_variable::timed wait: mutex not locked");
496
    nanoseconds __d = __tp.time_since_epoch();
497
    timespec __ts;
498
    seconds __s = duration_cast<seconds>(__d);
499
    using __ts_sec = decltype(__ts.tv_sec);
500
    const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
501
    if (__s.count() < __ts_sec_max)
502
    {
503
        __ts.tv_sec = static_cast<__ts_sec>(__s.count());
504
        __ts.tv_nsec = (__d - __s).count();
505
    }
506
    else
507
    {
508
        __ts.tv_sec = __ts_sec_max;
509
        __ts.tv_nsec = giga::num - 1;
510
    }
511
    int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts);
512
    if (__ec != 0 && __ec != ETIMEDOUT)
513
        __throw_system_error(__ec, "condition_variable timed_wait failed");
514
}
515
#endif // _LIBCPP_HAS_COND_CLOCKWAIT
516
517
template <class _Clock>
518
inline
519
void
520
condition_variable::__do_timed_wait(unique_lock<mutex>& __lk,
521
     chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT
522
{
523
    wait_for(__lk, __tp - _Clock::now());
524
}
525
526
#endif // !_LIBCPP_HAS_NO_THREADS
527
528
_LIBCPP_END_NAMESPACE_STD
529
530
_LIBCPP_POP_MACROS
531
532
#endif  // _LIBCPP___MUTEX_BASE