llvm-project

Форк
0
516 строк · 13.2 Кб
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 <__chrono/steady_clock.h>
190
#include <__chrono/time_point.h>
191
#include <__condition_variable/condition_variable.h>
192
#include <__config>
193
#include <__memory/shared_ptr.h>
194
#include <__mutex/lock_guard.h>
195
#include <__mutex/mutex.h>
196
#include <__mutex/once_flag.h>
197
#include <__mutex/tag_types.h>
198
#include <__mutex/unique_lock.h>
199
#include <__thread/id.h>
200
#include <__thread/support.h>
201
#include <__utility/forward.h>
202
#include <cstddef>
203
#include <limits>
204
#ifndef _LIBCPP_CXX03_LANG
205
#  include <tuple>
206
#endif
207
#include <version>
208

209
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
210
#  pragma GCC system_header
211
#endif
212

213
_LIBCPP_PUSH_MACROS
214
#include <__undef_macros>
215

216
_LIBCPP_BEGIN_NAMESPACE_STD
217

218
#ifndef _LIBCPP_HAS_NO_THREADS
219

220
class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex {
221
  __libcpp_recursive_mutex_t __m_;
222

223
public:
224
  recursive_mutex();
225
  ~recursive_mutex();
226

227
  recursive_mutex(const recursive_mutex&)            = delete;
228
  recursive_mutex& operator=(const recursive_mutex&) = delete;
229

230
  void lock();
231
  bool try_lock() _NOEXCEPT;
232
  void unlock() _NOEXCEPT;
233

234
  typedef __libcpp_recursive_mutex_t* native_handle_type;
235

236
  _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; }
237
};
238

239
class _LIBCPP_EXPORTED_FROM_ABI timed_mutex {
240
  mutex __m_;
241
  condition_variable __cv_;
242
  bool __locked_;
243

244
public:
245
  timed_mutex();
246
  ~timed_mutex();
247

248
  timed_mutex(const timed_mutex&)            = delete;
249
  timed_mutex& operator=(const timed_mutex&) = delete;
250

251
public:
252
  void lock();
253
  bool try_lock() _NOEXCEPT;
254
  template <class _Rep, class _Period>
255
  _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
256
    return try_lock_until(chrono::steady_clock::now() + __d);
257
  }
258
  template <class _Clock, class _Duration>
259
  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
260
  try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
261
  void unlock() _NOEXCEPT;
262
};
263

264
template <class _Clock, class _Duration>
265
bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
266
  using namespace chrono;
267
  unique_lock<mutex> __lk(__m_);
268
  bool __no_timeout = _Clock::now() < __t;
269
  while (__no_timeout && __locked_)
270
    __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
271
  if (!__locked_) {
272
    __locked_ = true;
273
    return true;
274
  }
275
  return false;
276
}
277

278
class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex {
279
  mutex __m_;
280
  condition_variable __cv_;
281
  size_t __count_;
282
  __thread_id __id_;
283

284
public:
285
  recursive_timed_mutex();
286
  ~recursive_timed_mutex();
287

288
  recursive_timed_mutex(const recursive_timed_mutex&)            = delete;
289
  recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
290

291
  void lock();
292
  bool try_lock() _NOEXCEPT;
293
  template <class _Rep, class _Period>
294
  _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
295
    return try_lock_until(chrono::steady_clock::now() + __d);
296
  }
297
  template <class _Clock, class _Duration>
298
  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
299
  try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
300
  void unlock() _NOEXCEPT;
301
};
302

303
template <class _Clock, class _Duration>
304
bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
305
  using namespace chrono;
306
  __thread_id __id = this_thread::get_id();
307
  unique_lock<mutex> __lk(__m_);
308
  if (__id == __id_) {
309
    if (__count_ == numeric_limits<size_t>::max())
310
      return false;
311
    ++__count_;
312
    return true;
313
  }
314
  bool __no_timeout = _Clock::now() < __t;
315
  while (__no_timeout && __count_ != 0)
316
    __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
317
  if (__count_ == 0) {
318
    __count_ = 1;
319
    __id_    = __id;
320
    return true;
321
  }
322
  return false;
323
}
324

325
template <class _L0, class _L1>
326
_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) {
327
  unique_lock<_L0> __u0(__l0, try_to_lock_t());
328
  if (__u0.owns_lock()) {
329
    if (__l1.try_lock()) {
330
      __u0.release();
331
      return -1;
332
    } else
333
      return 1;
334
  }
335
  return 0;
336
}
337

338
#  ifndef _LIBCPP_CXX03_LANG
339

340
template <class _L0, class _L1, class _L2, class... _L3>
341
_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
342
  int __r = 0;
343
  unique_lock<_L0> __u0(__l0, try_to_lock);
344
  if (__u0.owns_lock()) {
345
    __r = std::try_lock(__l1, __l2, __l3...);
346
    if (__r == -1)
347
      __u0.release();
348
    else
349
      ++__r;
350
  }
351
  return __r;
352
}
353

354
#  endif // _LIBCPP_CXX03_LANG
355

356
template <class _L0, class _L1>
357
_LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) {
358
  while (true) {
359
    {
360
      unique_lock<_L0> __u0(__l0);
361
      if (__l1.try_lock()) {
362
        __u0.release();
363
        break;
364
      }
365
    }
366
    __libcpp_thread_yield();
367
    {
368
      unique_lock<_L1> __u1(__l1);
369
      if (__l0.try_lock()) {
370
        __u1.release();
371
        break;
372
      }
373
    }
374
    __libcpp_thread_yield();
375
  }
376
}
377

378
#  ifndef _LIBCPP_CXX03_LANG
379

380
template <class _L0, class _L1, class _L2, class... _L3>
381
void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
382
  while (true) {
383
    switch (__i) {
384
    case 0: {
385
      unique_lock<_L0> __u0(__l0);
386
      __i = std::try_lock(__l1, __l2, __l3...);
387
      if (__i == -1) {
388
        __u0.release();
389
        return;
390
      }
391
    }
392
      ++__i;
393
      __libcpp_thread_yield();
394
      break;
395
    case 1: {
396
      unique_lock<_L1> __u1(__l1);
397
      __i = std::try_lock(__l2, __l3..., __l0);
398
      if (__i == -1) {
399
        __u1.release();
400
        return;
401
      }
402
    }
403
      if (__i == sizeof...(_L3) + 1)
404
        __i = 0;
405
      else
406
        __i += 2;
407
      __libcpp_thread_yield();
408
      break;
409
    default:
410
      std::__lock_first(__i - 2, __l2, __l3..., __l0, __l1);
411
      return;
412
    }
413
  }
414
}
415

416
template <class _L0, class _L1, class _L2, class... _L3>
417
inline _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
418
  std::__lock_first(0, __l0, __l1, __l2, __l3...);
419
}
420

421
#  endif // _LIBCPP_CXX03_LANG
422

423
#  if _LIBCPP_STD_VER >= 17
424
template <class... _Mutexes>
425
class _LIBCPP_TEMPLATE_VIS scoped_lock;
426

427
template <>
428
class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
429
public:
430
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock() {}
431
  ~scoped_lock() = default;
432

433
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {}
434

435
  scoped_lock(scoped_lock const&)            = delete;
436
  scoped_lock& operator=(scoped_lock const&) = delete;
437
};
438

439
template <class _Mutex>
440
class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
441
public:
442
  typedef _Mutex mutex_type;
443

444
private:
445
  mutex_type& __m_;
446

447
public:
448
  [[nodiscard]]
449
  _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
450
      : __m_(__m) {
451
    __m_.lock();
452
  }
453

454
  ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
455

456
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
457
      _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
458
      : __m_(__m) {}
459

460
  scoped_lock(scoped_lock const&)            = delete;
461
  scoped_lock& operator=(scoped_lock const&) = delete;
462
};
463

464
template <class... _MArgs>
465
class _LIBCPP_TEMPLATE_VIS scoped_lock {
466
  static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
467
  typedef tuple<_MArgs&...> _MutexTuple;
468

469
public:
470
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) {
471
    std::lock(__margs...);
472
  }
473

474
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {}
475

476
  _LIBCPP_HIDE_FROM_ABI ~scoped_lock() {
477
    typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
478
    __unlock_unpack(_Indices{}, __t_);
479
  }
480

481
  scoped_lock(scoped_lock const&)            = delete;
482
  scoped_lock& operator=(scoped_lock const&) = delete;
483

484
private:
485
  template <size_t... _Indx>
486
  _LIBCPP_HIDE_FROM_ABI static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
487
    (std::get<_Indx>(__mt).unlock(), ...);
488
  }
489

490
  _MutexTuple __t_;
491
};
492
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock);
493

494
#  endif // _LIBCPP_STD_VER >= 17
495
#endif   // !_LIBCPP_HAS_NO_THREADS
496

497
_LIBCPP_END_NAMESPACE_STD
498

499
_LIBCPP_POP_MACROS
500

501
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
502
#  include <atomic>
503
#  include <concepts>
504
#  include <cstdlib>
505
#  include <cstring>
506
#  include <ctime>
507
#  include <initializer_list>
508
#  include <iosfwd>
509
#  include <new>
510
#  include <stdexcept>
511
#  include <system_error>
512
#  include <type_traits>
513
#  include <typeinfo>
514
#endif
515

516
#endif // _LIBCPP_MUTEX
517

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.