Coverage Report

Created: 2025-08-28 06:28

/src/llvm-project-18.1.8.build/include/c++/v1/mutex
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
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;  // Only if sizeof...(MutexTypes) == 1
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 <__assert> // all public C++ headers provide the assertion handler
190
#include <__chrono/steady_clock.h>
191
#include <__chrono/time_point.h>
192
#include <__condition_variable/condition_variable.h>
193
#include <__config>
194
#include <__memory/shared_ptr.h>
195
#include <__mutex/lock_guard.h>
196
#include <__mutex/mutex.h>
197
#include <__mutex/once_flag.h>
198
#include <__mutex/tag_types.h>
199
#include <__mutex/unique_lock.h>
200
#include <__thread/id.h>
201
#include <__threading_support>
202
#include <__utility/forward.h>
203
#include <cstddef>
204
#include <limits>
205
#ifndef _LIBCPP_CXX03_LANG
206
#  include <tuple>
207
#endif
208
#include <version>
209
210
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
211
#  pragma GCC system_header
212
#endif
213
214
_LIBCPP_PUSH_MACROS
215
#include <__undef_macros>
216
217
_LIBCPP_BEGIN_NAMESPACE_STD
218
219
#ifndef _LIBCPP_HAS_NO_THREADS
220
221
class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex {
222
  __libcpp_recursive_mutex_t __m_;
223
224
public:
225
  recursive_mutex();
226
  ~recursive_mutex();
227
228
  recursive_mutex(const recursive_mutex&)            = delete;
229
  recursive_mutex& operator=(const recursive_mutex&) = delete;
230
231
  void lock();
232
  bool try_lock() _NOEXCEPT;
233
  void unlock() _NOEXCEPT;
234
235
  typedef __libcpp_recursive_mutex_t* native_handle_type;
236
237
0
  _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; }
238
};
239
240
class _LIBCPP_EXPORTED_FROM_ABI timed_mutex {
241
  mutex __m_;
242
  condition_variable __cv_;
243
  bool __locked_;
244
245
public:
246
  timed_mutex();
247
  ~timed_mutex();
248
249
  timed_mutex(const timed_mutex&)            = delete;
250
  timed_mutex& operator=(const timed_mutex&) = delete;
251
252
public:
253
  void lock();
254
  bool try_lock() _NOEXCEPT;
255
  template <class _Rep, class _Period>
256
  _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
257
    return try_lock_until(chrono::steady_clock::now() + __d);
258
  }
259
  template <class _Clock, class _Duration>
260
  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
261
  try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
262
  void unlock() _NOEXCEPT;
263
};
264
265
template <class _Clock, class _Duration>
266
bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
267
  using namespace chrono;
268
  unique_lock<mutex> __lk(__m_);
269
  bool __no_timeout = _Clock::now() < __t;
270
  while (__no_timeout && __locked_)
271
    __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
272
  if (!__locked_) {
273
    __locked_ = true;
274
    return true;
275
  }
276
  return false;
277
}
278
279
class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex {
280
  mutex __m_;
281
  condition_variable __cv_;
282
  size_t __count_;
283
  __thread_id __id_;
284
285
public:
286
  recursive_timed_mutex();
287
  ~recursive_timed_mutex();
288
289
  recursive_timed_mutex(const recursive_timed_mutex&)            = delete;
290
  recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
291
292
  void lock();
293
  bool try_lock() _NOEXCEPT;
294
  template <class _Rep, class _Period>
295
  _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
296
    return try_lock_until(chrono::steady_clock::now() + __d);
297
  }
298
  template <class _Clock, class _Duration>
299
  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
300
  try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
301
  void unlock() _NOEXCEPT;
302
};
303
304
template <class _Clock, class _Duration>
305
bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
306
  using namespace chrono;
307
  __thread_id __id = this_thread::get_id();
308
  unique_lock<mutex> __lk(__m_);
309
  if (__id == __id_) {
310
    if (__count_ == numeric_limits<size_t>::max())
311
      return false;
312
    ++__count_;
313
    return true;
314
  }
315
  bool __no_timeout = _Clock::now() < __t;
316
  while (__no_timeout && __count_ != 0)
317
    __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
318
  if (__count_ == 0) {
319
    __count_ = 1;
320
    __id_    = __id;
321
    return true;
322
  }
323
  return false;
324
}
325
326
template <class _L0, class _L1>
327
_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) {
328
  unique_lock<_L0> __u0(__l0, try_to_lock_t());
329
  if (__u0.owns_lock()) {
330
    if (__l1.try_lock()) {
331
      __u0.release();
332
      return -1;
333
    } else
334
      return 1;
335
  }
336
  return 0;
337
}
338
339
#  ifndef _LIBCPP_CXX03_LANG
340
341
template <class _L0, class _L1, class _L2, class... _L3>
342
_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
343
  int __r = 0;
344
  unique_lock<_L0> __u0(__l0, try_to_lock);
345
  if (__u0.owns_lock()) {
346
    __r = std::try_lock(__l1, __l2, __l3...);
347
    if (__r == -1)
348
      __u0.release();
349
    else
350
      ++__r;
351
  }
352
  return __r;
353
}
354
355
#  endif // _LIBCPP_CXX03_LANG
356
357
template <class _L0, class _L1>
358
_LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) {
359
  while (true) {
360
    {
361
      unique_lock<_L0> __u0(__l0);
362
      if (__l1.try_lock()) {
363
        __u0.release();
364
        break;
365
      }
366
    }
367
    __libcpp_thread_yield();
368
    {
369
      unique_lock<_L1> __u1(__l1);
370
      if (__l0.try_lock()) {
371
        __u1.release();
372
        break;
373
      }
374
    }
375
    __libcpp_thread_yield();
376
  }
377
}
378
379
#  ifndef _LIBCPP_CXX03_LANG
380
381
template <class _L0, class _L1, class _L2, class... _L3>
382
void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
383
  while (true) {
384
    switch (__i) {
385
    case 0: {
386
      unique_lock<_L0> __u0(__l0);
387
      __i = std::try_lock(__l1, __l2, __l3...);
388
      if (__i == -1) {
389
        __u0.release();
390
        return;
391
      }
392
    }
393
      ++__i;
394
      __libcpp_thread_yield();
395
      break;
396
    case 1: {
397
      unique_lock<_L1> __u1(__l1);
398
      __i = std::try_lock(__l2, __l3..., __l0);
399
      if (__i == -1) {
400
        __u1.release();
401
        return;
402
      }
403
    }
404
      if (__i == sizeof...(_L3) + 1)
405
        __i = 0;
406
      else
407
        __i += 2;
408
      __libcpp_thread_yield();
409
      break;
410
    default:
411
      std::__lock_first(__i - 2, __l2, __l3..., __l0, __l1);
412
      return;
413
    }
414
  }
415
}
416
417
template <class _L0, class _L1, class _L2, class... _L3>
418
inline _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
419
  std::__lock_first(0, __l0, __l1, __l2, __l3...);
420
}
421
422
template <class _L0>
423
inline _LIBCPP_HIDE_FROM_ABI void __unlock(_L0& __l0) {
424
  __l0.unlock();
425
}
426
427
template <class _L0, class _L1>
428
inline _LIBCPP_HIDE_FROM_ABI void __unlock(_L0& __l0, _L1& __l1) {
429
  __l0.unlock();
430
  __l1.unlock();
431
}
432
433
template <class _L0, class _L1, class _L2, class... _L3>
434
inline _LIBCPP_HIDE_FROM_ABI void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
435
  __l0.unlock();
436
  __l1.unlock();
437
  std::__unlock(__l2, __l3...);
438
}
439
440
#  endif // _LIBCPP_CXX03_LANG
441
442
#  if _LIBCPP_STD_VER >= 17
443
template <class... _Mutexes>
444
class _LIBCPP_TEMPLATE_VIS scoped_lock;
445
446
template <>
447
class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
448
public:
449
0
  explicit scoped_lock() {}
450
  ~scoped_lock() = default;
451
452
0
  _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {}
453
454
  scoped_lock(scoped_lock const&)            = delete;
455
  scoped_lock& operator=(scoped_lock const&) = delete;
456
};
457
458
template <class _Mutex>
459
class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
460
public:
461
  typedef _Mutex mutex_type;
462
463
private:
464
  mutex_type& __m_;
465
466
public:
467
  explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) {
468
    __m_.lock();
469
  }
470
471
  ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
472
473
  _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
474
      _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
475
      : __m_(__m) {}
476
477
  scoped_lock(scoped_lock const&)            = delete;
478
  scoped_lock& operator=(scoped_lock const&) = delete;
479
};
480
481
template <class... _MArgs>
482
class _LIBCPP_TEMPLATE_VIS scoped_lock {
483
  static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
484
  typedef tuple<_MArgs&...> _MutexTuple;
485
486
public:
487
  _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) { std::lock(__margs...); }
488
489
  _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {}
490
491
  _LIBCPP_HIDE_FROM_ABI ~scoped_lock() {
492
    typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
493
    __unlock_unpack(_Indices{}, __t_);
494
  }
495
496
  scoped_lock(scoped_lock const&)            = delete;
497
  scoped_lock& operator=(scoped_lock const&) = delete;
498
499
private:
500
  template <size_t... _Indx>
501
  _LIBCPP_HIDE_FROM_ABI static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
502
    std::__unlock(std::get<_Indx>(__mt)...);
503
  }
504
505
  _MutexTuple __t_;
506
};
507
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock);
508
509
#  endif // _LIBCPP_STD_VER >= 17
510
#endif   // !_LIBCPP_HAS_NO_THREADS
511
512
_LIBCPP_END_NAMESPACE_STD
513
514
_LIBCPP_POP_MACROS
515
516
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
517
#  include <atomic>
518
#  include <concepts>
519
#  include <cstdlib>
520
#  include <cstring>
521
#  include <ctime>
522
#  include <initializer_list>
523
#  include <iosfwd>
524
#  include <new>
525
#  include <stdexcept>
526
#  include <system_error>
527
#  include <type_traits>
528
#  include <typeinfo>
529
#endif
530
531
#endif // _LIBCPP_MUTEX