Coverage Report

Created: 2020-07-11 14:00

/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/include/mutex
Line
Count
Source (jump to first uncovered line)
1
// -*- C++ -*-
2
//===--------------------------- mutex ------------------------------------===//
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
11
#define _LIBCPP_MUTEX
12
13
/*
14
    mutex synopsis
15
16
namespace std
17
{
18
19
class mutex
20
{
21
public:
22
     constexpr mutex() noexcept;
23
     ~mutex();
24
25
    mutex(const mutex&) = delete;
26
    mutex& operator=(const mutex&) = delete;
27
28
    void lock();
29
    bool try_lock();
30
    void unlock();
31
32
    typedef pthread_mutex_t* native_handle_type;
33
    native_handle_type native_handle();
34
};
35
36
class recursive_mutex
37
{
38
public:
39
     recursive_mutex();
40
     ~recursive_mutex();
41
42
    recursive_mutex(const recursive_mutex&) = delete;
43
    recursive_mutex& operator=(const recursive_mutex&) = delete;
44
45
    void lock();
46
    bool try_lock() noexcept;
47
    void unlock();
48
49
    typedef pthread_mutex_t* native_handle_type;
50
    native_handle_type native_handle();
51
};
52
53
class timed_mutex
54
{
55
public:
56
     timed_mutex();
57
     ~timed_mutex();
58
59
    timed_mutex(const timed_mutex&) = delete;
60
    timed_mutex& operator=(const timed_mutex&) = delete;
61
62
    void lock();
63
    bool try_lock();
64
    template <class Rep, class Period>
65
        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
66
    template <class Clock, class Duration>
67
        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
68
    void unlock();
69
};
70
71
class recursive_timed_mutex
72
{
73
public:
74
     recursive_timed_mutex();
75
     ~recursive_timed_mutex();
76
77
    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
78
    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
79
80
    void lock();
81
    bool try_lock() noexcept;
82
    template <class Rep, class Period>
83
        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
84
    template <class Clock, class Duration>
85
        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
86
    void unlock();
87
};
88
89
struct defer_lock_t { explicit defer_lock_t() = default; };
90
struct try_to_lock_t { explicit try_to_lock_t() = default; };
91
struct adopt_lock_t { explicit adopt_lock_t() = default; };
92
93
inline constexpr defer_lock_t  defer_lock{};
94
inline constexpr try_to_lock_t try_to_lock{};
95
inline constexpr adopt_lock_t  adopt_lock{};
96
97
template <class Mutex>
98
class lock_guard
99
{
100
public:
101
    typedef Mutex mutex_type;
102
103
    explicit lock_guard(mutex_type& m);
104
    lock_guard(mutex_type& m, adopt_lock_t);
105
    ~lock_guard();
106
107
    lock_guard(lock_guard const&) = delete;
108
    lock_guard& operator=(lock_guard const&) = delete;
109
};
110
111
template <class... MutexTypes>
112
class scoped_lock // C++17
113
{
114
public:
115
    using mutex_type = Mutex;  // If MutexTypes... consists of the single type Mutex
116
117
    explicit scoped_lock(MutexTypes&... m);
118
    scoped_lock(adopt_lock_t, MutexTypes&... m);
119
    ~scoped_lock();
120
    scoped_lock(scoped_lock const&) = delete;
121
    scoped_lock& operator=(scoped_lock const&) = delete;
122
private:
123
    tuple<MutexTypes&...> pm; // exposition only
124
};
125
126
template <class Mutex>
127
class unique_lock
128
{
129
public:
130
    typedef Mutex mutex_type;
131
    unique_lock() noexcept;
132
    explicit unique_lock(mutex_type& m);
133
    unique_lock(mutex_type& m, defer_lock_t) noexcept;
134
    unique_lock(mutex_type& m, try_to_lock_t);
135
    unique_lock(mutex_type& m, adopt_lock_t);
136
    template <class Clock, class Duration>
137
        unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
138
    template <class Rep, class Period>
139
        unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
140
    ~unique_lock();
141
142
    unique_lock(unique_lock const&) = delete;
143
    unique_lock& operator=(unique_lock const&) = delete;
144
145
    unique_lock(unique_lock&& u) noexcept;
146
    unique_lock& operator=(unique_lock&& u) noexcept;
147
148
    void lock();
149
    bool try_lock();
150
151
    template <class Rep, class Period>
152
        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
153
    template <class Clock, class Duration>
154
        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
155
156
    void unlock();
157
158
    void swap(unique_lock& u) noexcept;
159
    mutex_type* release() noexcept;
160
161
    bool owns_lock() const noexcept;
162
    explicit operator bool () const noexcept;
163
    mutex_type* mutex() const noexcept;
164
};
165
166
template <class Mutex>
167
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
168
169
template <class L1, class L2, class... L3>
170
  int try_lock(L1&, L2&, L3&...);
171
template <class L1, class L2, class... L3>
172
  void lock(L1&, L2&, L3&...);
173
174
struct once_flag
175
{
176
    constexpr once_flag() noexcept;
177
178
    once_flag(const once_flag&) = delete;
179
    once_flag& operator=(const once_flag&) = delete;
180
};
181
182
template<class Callable, class ...Args>
183
  void call_once(once_flag& flag, Callable&& func, Args&&... args);
184
185
}  // std
186
187
*/
188
189
#include <__config>
190
#include <__mutex_base>
191
#include <cstdint>
192
#include <functional>
193
#include <memory>
194
#ifndef _LIBCPP_CXX03_LANG
195
#include <tuple>
196
#endif
197
#include <version>
198
#include <__threading_support>
199
200
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
201
#pragma GCC system_header
202
#endif
203
204
_LIBCPP_PUSH_MACROS
205
#include <__undef_macros>
206
207
208
_LIBCPP_BEGIN_NAMESPACE_STD
209
210
#ifndef _LIBCPP_HAS_NO_THREADS
211
212
class _LIBCPP_TYPE_VIS recursive_mutex
213
{
214
    __libcpp_recursive_mutex_t __m_;
215
216
public:
217
     recursive_mutex();
218
     ~recursive_mutex();
219
220
private:
221
    recursive_mutex(const recursive_mutex&); // = delete;
222
    recursive_mutex& operator=(const recursive_mutex&); // = delete;
223
224
public:
225
    void lock();
226
    bool try_lock() _NOEXCEPT;
227
    void unlock()  _NOEXCEPT;
228
229
    typedef __libcpp_recursive_mutex_t* native_handle_type;
230
231
    _LIBCPP_INLINE_VISIBILITY
232
0
    native_handle_type native_handle() {return &__m_;}
233
};
234
235
class _LIBCPP_TYPE_VIS timed_mutex
236
{
237
    mutex              __m_;
238
    condition_variable __cv_;
239
    bool               __locked_;
240
public:
241
     timed_mutex();
242
     ~timed_mutex();
243
244
private:
245
    timed_mutex(const timed_mutex&); // = delete;
246
    timed_mutex& operator=(const timed_mutex&); // = delete;
247
248
public:
249
    void lock();
250
    bool try_lock() _NOEXCEPT;
251
    template <class _Rep, class _Period>
252
        _LIBCPP_INLINE_VISIBILITY
253
        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
254
            {return try_lock_until(chrono::steady_clock::now() + __d);}
255
    template <class _Clock, class _Duration>
256
        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
257
        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
258
    void unlock() _NOEXCEPT;
259
};
260
261
template <class _Clock, class _Duration>
262
bool
263
timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
264
{
265
    using namespace chrono;
266
    unique_lock<mutex> __lk(__m_);
267
    bool no_timeout = _Clock::now() < __t;
268
    while (no_timeout && __locked_)
269
        no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
270
    if (!__locked_)
271
    {
272
        __locked_ = true;
273
        return true;
274
    }
275
    return false;
276
}
277
278
class _LIBCPP_TYPE_VIS recursive_timed_mutex
279
{
280
    mutex              __m_;
281
    condition_variable __cv_;
282
    size_t             __count_;
283
    __thread_id        __id_;
284
public:
285
     recursive_timed_mutex();
286
     ~recursive_timed_mutex();
287
288
private:
289
    recursive_timed_mutex(const recursive_timed_mutex&); // = delete;
290
    recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete;
291
292
public:
293
    void lock();
294
    bool try_lock() _NOEXCEPT;
295
    template <class _Rep, class _Period>
296
        _LIBCPP_INLINE_VISIBILITY
297
        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
298
            {return try_lock_until(chrono::steady_clock::now() + __d);}
299
    template <class _Clock, class _Duration>
300
        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
301
        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
302
    void unlock() _NOEXCEPT;
303
};
304
305
template <class _Clock, class _Duration>
306
bool
307
recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
308
{
309
    using namespace chrono;
310
    __thread_id __id = this_thread::get_id();
311
    unique_lock<mutex> lk(__m_);
312
    if (__id == __id_)
313
    {
314
        if (__count_ == numeric_limits<size_t>::max())
315
            return false;
316
        ++__count_;
317
        return true;
318
    }
319
    bool no_timeout = _Clock::now() < __t;
320
    while (no_timeout && __count_ != 0)
321
        no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
322
    if (__count_ == 0)
323
    {
324
        __count_ = 1;
325
        __id_ = __id;
326
        return true;
327
    }
328
    return false;
329
}
330
331
template <class _L0, class _L1>
332
int
333
try_lock(_L0& __l0, _L1& __l1)
334
{
335
    unique_lock<_L0> __u0(__l0, try_to_lock);
336
    if (__u0.owns_lock())
337
    {
338
        if (__l1.try_lock())
339
        {
340
            __u0.release();
341
            return -1;
342
        }
343
        else
344
            return 1;
345
    }
346
    return 0;
347
}
348
349
#ifndef _LIBCPP_CXX03_LANG
350
351
template <class _L0, class _L1, class _L2, class... _L3>
352
int
353
try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
354
{
355
    int __r = 0;
356
    unique_lock<_L0> __u0(__l0, try_to_lock);
357
    if (__u0.owns_lock())
358
    {
359
        __r = try_lock(__l1, __l2, __l3...);
360
        if (__r == -1)
361
            __u0.release();
362
        else
363
            ++__r;
364
    }
365
    return __r;
366
}
367
368
#endif  // _LIBCPP_CXX03_LANG
369
370
template <class _L0, class _L1>
371
void
372
lock(_L0& __l0, _L1& __l1)
373
{
374
    while (true)
375
    {
376
        {
377
            unique_lock<_L0> __u0(__l0);
378
            if (__l1.try_lock())
379
            {
380
                __u0.release();
381
                break;
382
            }
383
        }
384
        __libcpp_thread_yield();
385
        {
386
            unique_lock<_L1> __u1(__l1);
387
            if (__l0.try_lock())
388
            {
389
                __u1.release();
390
                break;
391
            }
392
        }
393
        __libcpp_thread_yield();
394
    }
395
}
396
397
#ifndef _LIBCPP_CXX03_LANG
398
399
template <class _L0, class _L1, class _L2, class ..._L3>
400
void
401
__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
402
{
403
    while (true)
404
    {
405
        switch (__i)
406
        {
407
        case 0:
408
            {
409
                unique_lock<_L0> __u0(__l0);
410
                __i = try_lock(__l1, __l2, __l3...);
411
                if (__i == -1)
412
                {
413
                    __u0.release();
414
                    return;
415
                }
416
            }
417
            ++__i;
418
            __libcpp_thread_yield();
419
            break;
420
        case 1:
421
            {
422
                unique_lock<_L1> __u1(__l1);
423
                __i = try_lock(__l2, __l3..., __l0);
424
                if (__i == -1)
425
                {
426
                    __u1.release();
427
                    return;
428
                }
429
            }
430
            if (__i == sizeof...(_L3) + 1)
431
                __i = 0;
432
            else
433
                __i += 2;
434
            __libcpp_thread_yield();
435
            break;
436
        default:
437
            __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
438
            return;
439
        }
440
    }
441
}
442
443
template <class _L0, class _L1, class _L2, class ..._L3>
444
inline _LIBCPP_INLINE_VISIBILITY
445
void
446
lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
447
{
448
    __lock_first(0, __l0, __l1, __l2, __l3...);
449
}
450
451
template <class _L0>
452
inline _LIBCPP_INLINE_VISIBILITY
453
void __unlock(_L0& __l0) {
454
    __l0.unlock();
455
}
456
457
template <class _L0, class _L1>
458
inline _LIBCPP_INLINE_VISIBILITY
459
void __unlock(_L0& __l0, _L1& __l1) {
460
    __l0.unlock();
461
    __l1.unlock();
462
}
463
464
template <class _L0, class _L1, class _L2, class ..._L3>
465
inline _LIBCPP_INLINE_VISIBILITY
466
void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
467
    __l0.unlock();
468
    __l1.unlock();
469
    _VSTD::__unlock(__l2, __l3...);
470
}
471
472
#endif  // _LIBCPP_CXX03_LANG
473
474
#if _LIBCPP_STD_VER > 14
475
template <class ..._Mutexes>
476
class _LIBCPP_TEMPLATE_VIS scoped_lock;
477
478
template <>
479
class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
480
public:
481
    explicit scoped_lock() {}
482
    ~scoped_lock() = default;
483
484
    _LIBCPP_INLINE_VISIBILITY
485
    explicit scoped_lock(adopt_lock_t) {}
486
487
    scoped_lock(scoped_lock const&) = delete;
488
    scoped_lock& operator=(scoped_lock const&) = delete;
489
};
490
491
template <class _Mutex>
492
class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
493
public:
494
    typedef _Mutex  mutex_type;
495
private:
496
    mutex_type& __m_;
497
public:
498
    explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
499
        : __m_(__m) {__m_.lock();}
500
501
    ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
502
503
    _LIBCPP_INLINE_VISIBILITY
504
    explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
505
        : __m_(__m) {}
506
507
    scoped_lock(scoped_lock const&) = delete;
508
    scoped_lock& operator=(scoped_lock const&) = delete;
509
};
510
511
template <class ..._MArgs>
512
class _LIBCPP_TEMPLATE_VIS scoped_lock
513
{
514
    static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
515
    typedef tuple<_MArgs&...> _MutexTuple;
516
517
public:
518
    _LIBCPP_INLINE_VISIBILITY
519
    explicit scoped_lock(_MArgs&... __margs)
520
      : __t_(__margs...)
521
    {
522
        _VSTD::lock(__margs...);
523
    }
524
525
    _LIBCPP_INLINE_VISIBILITY
526
    scoped_lock(adopt_lock_t, _MArgs&... __margs)
527
        : __t_(__margs...)
528
    {
529
    }
530
531
    _LIBCPP_INLINE_VISIBILITY
532
    ~scoped_lock() {
533
        typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
534
        __unlock_unpack(_Indices{}, __t_);
535
    }
536
537
    scoped_lock(scoped_lock const&) = delete;
538
    scoped_lock& operator=(scoped_lock const&) = delete;
539
540
private:
541
    template <size_t ..._Indx>
542
    _LIBCPP_INLINE_VISIBILITY
543
    static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
544
        _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...);
545
    }
546
547
    _MutexTuple __t_;
548
};
549
550
#endif // _LIBCPP_STD_VER > 14
551
#endif // !_LIBCPP_HAS_NO_THREADS
552
553
struct _LIBCPP_TEMPLATE_VIS once_flag;
554
555
#ifndef _LIBCPP_CXX03_LANG
556
557
template<class _Callable, class... _Args>
558
_LIBCPP_INLINE_VISIBILITY
559
void call_once(once_flag&, _Callable&&, _Args&&...);
560
561
#else  // _LIBCPP_CXX03_LANG
562
563
template<class _Callable>
564
_LIBCPP_INLINE_VISIBILITY
565
void call_once(once_flag&, _Callable&);
566
567
template<class _Callable>
568
_LIBCPP_INLINE_VISIBILITY
569
void call_once(once_flag&, const _Callable&);
570
571
#endif  // _LIBCPP_CXX03_LANG
572
573
struct _LIBCPP_TEMPLATE_VIS once_flag
574
{
575
    _LIBCPP_INLINE_VISIBILITY
576
    _LIBCPP_CONSTEXPR
577
        once_flag() _NOEXCEPT : __state_(0) {}
578
579
#if defined(_LIBCPP_ABI_MICROSOFT)
580
   typedef uintptr_t _State_type;
581
#else
582
   typedef unsigned long _State_type;
583
#endif
584
585
586
private:
587
    once_flag(const once_flag&); // = delete;
588
    once_flag& operator=(const once_flag&); // = delete;
589
590
    _State_type __state_;
591
592
#ifndef _LIBCPP_CXX03_LANG
593
    template<class _Callable, class... _Args>
594
    friend
595
    void call_once(once_flag&, _Callable&&, _Args&&...);
596
#else  // _LIBCPP_CXX03_LANG
597
    template<class _Callable>
598
    friend
599
    void call_once(once_flag&, _Callable&);
600
601
    template<class _Callable>
602
    friend
603
    void call_once(once_flag&, const _Callable&);
604
#endif  // _LIBCPP_CXX03_LANG
605
};
606
607
#ifndef _LIBCPP_CXX03_LANG
608
609
template <class _Fp>
610
class __call_once_param
611
{
612
    _Fp& __f_;
613
public:
614
    _LIBCPP_INLINE_VISIBILITY
615
238k
    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
616
617
    _LIBCPP_INLINE_VISIBILITY
618
    void operator()()
619
238k
    {
620
238k
        typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
621
238k
        __execute(_Index());
622
238k
    }
623
624
private:
625
    template <size_t ..._Indices>
626
    _LIBCPP_INLINE_VISIBILITY
627
    void __execute(__tuple_indices<_Indices...>)
628
238k
    {
629
238k
        __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
630
238k
    }
631
};
632
633
#else
634
635
template <class _Fp>
636
class __call_once_param
637
{
638
    _Fp& __f_;
639
public:
640
    _LIBCPP_INLINE_VISIBILITY
641
    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
642
643
    _LIBCPP_INLINE_VISIBILITY
644
    void operator()()
645
    {
646
        __f_();
647
    }
648
};
649
650
#endif
651
652
template <class _Fp>
653
void _LIBCPP_INLINE_VISIBILITY
654
__call_once_proxy(void* __vp)
655
238k
{
656
238k
    __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
657
238k
    (*__p)();
658
238k
}
659
660
_LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*,
661
                                  void (*)(void*));
662
663
#ifndef _LIBCPP_CXX03_LANG
664
665
template<class _Callable, class... _Args>
666
inline _LIBCPP_INLINE_VISIBILITY
667
void
668
call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
669
19.6M
{
670
19.6M
    if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
671
238k
    {
672
238k
        typedef tuple<_Callable&&, _Args&&...> _Gp;
673
238k
        _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
674
238k
        __call_once_param<_Gp> __p(__f);
675
238k
        __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
676
238k
    }
677
19.6M
}
678
679
#else  // _LIBCPP_CXX03_LANG
680
681
template<class _Callable>
682
inline _LIBCPP_INLINE_VISIBILITY
683
void
684
call_once(once_flag& __flag, _Callable& __func)
685
{
686
    if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
687
    {
688
        __call_once_param<_Callable> __p(__func);
689
        __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
690
    }
691
}
692
693
template<class _Callable>
694
inline _LIBCPP_INLINE_VISIBILITY
695
void
696
call_once(once_flag& __flag, const _Callable& __func)
697
{
698
    if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
699
    {
700
        __call_once_param<const _Callable> __p(__func);
701
        __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
702
    }
703
}
704
705
#endif  // _LIBCPP_CXX03_LANG
706
707
_LIBCPP_END_NAMESPACE_STD
708
709
_LIBCPP_POP_MACROS
710
711
#endif  // _LIBCPP_MUTEX