[rtsan] Remove mkfifoat interceptor (#116997)
[llvm-project.git] / libcxx / include / mutex
blobecbfc5607dcc7828d56a7976edc7fb7fa1019d10
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 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_MUTEX
11 #define _LIBCPP_MUTEX
14     mutex synopsis
16 namespace std
19 class mutex
21 public:
22      constexpr mutex() noexcept;
23      ~mutex();
25     mutex(const mutex&) = delete;
26     mutex& operator=(const mutex&) = delete;
28     void lock();
29     bool try_lock();
30     void unlock();
32     typedef pthread_mutex_t* native_handle_type;
33     native_handle_type native_handle();
36 class recursive_mutex
38 public:
39      recursive_mutex();
40      ~recursive_mutex();
42     recursive_mutex(const recursive_mutex&) = delete;
43     recursive_mutex& operator=(const recursive_mutex&) = delete;
45     void lock();
46     bool try_lock() noexcept;
47     void unlock();
49     typedef pthread_mutex_t* native_handle_type;
50     native_handle_type native_handle();
53 class timed_mutex
55 public:
56      timed_mutex();
57      ~timed_mutex();
59     timed_mutex(const timed_mutex&) = delete;
60     timed_mutex& operator=(const timed_mutex&) = delete;
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();
71 class recursive_timed_mutex
73 public:
74      recursive_timed_mutex();
75      ~recursive_timed_mutex();
77     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
78     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
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();
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; };
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{};
97 template <class Mutex>
98 class lock_guard
100 public:
101     typedef Mutex mutex_type;
103     explicit lock_guard(mutex_type& m);
104     lock_guard(mutex_type& m, adopt_lock_t);
105     ~lock_guard();
107     lock_guard(lock_guard const&) = delete;
108     lock_guard& operator=(lock_guard const&) = delete;
111 template <class... MutexTypes>
112 class scoped_lock // C++17
114 public:
115     using mutex_type = Mutex;  // Only if sizeof...(MutexTypes) == 1
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
126 template <class Mutex>
127 class unique_lock
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();
142     unique_lock(unique_lock const&) = delete;
143     unique_lock& operator=(unique_lock const&) = delete;
145     unique_lock(unique_lock&& u) noexcept;
146     unique_lock& operator=(unique_lock&& u) noexcept;
148     void lock();
149     bool try_lock();
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);
156     void unlock();
158     void swap(unique_lock& u) noexcept;
159     mutex_type* release() noexcept;
161     bool owns_lock() const noexcept;
162     explicit operator bool () const noexcept;
163     mutex_type* mutex() const noexcept;
166 template <class Mutex>
167   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
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&...);
174 struct once_flag
176     constexpr once_flag() noexcept;
178     once_flag(const once_flag&) = delete;
179     once_flag& operator=(const once_flag&) = delete;
182 template<class Callable, class ...Args>
183   void call_once(once_flag& flag, Callable&& func, Args&&... args);
185 }  // std
189 #include <__chrono/steady_clock.h>
190 #include <__chrono/time_point.h>
191 #include <__condition_variable/condition_variable.h>
192 #include <__config>
193 #include <__mutex/lock_guard.h>
194 #include <__mutex/mutex.h>
195 #include <__mutex/once_flag.h>
196 #include <__mutex/tag_types.h>
197 #include <__mutex/unique_lock.h>
198 #include <__thread/id.h>
199 #include <__thread/support.h>
200 #include <__utility/forward.h>
201 #include <limits>
202 #ifndef _LIBCPP_CXX03_LANG
203 #  include <tuple>
204 #endif
205 #include <version>
207 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
208 #  pragma GCC system_header
209 #endif
211 _LIBCPP_PUSH_MACROS
212 #include <__undef_macros>
214 _LIBCPP_BEGIN_NAMESPACE_STD
216 #if _LIBCPP_HAS_THREADS
218 class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex {
219   __libcpp_recursive_mutex_t __m_;
221 public:
222   recursive_mutex();
223   ~recursive_mutex();
225   recursive_mutex(const recursive_mutex&)            = delete;
226   recursive_mutex& operator=(const recursive_mutex&) = delete;
228   void lock();
229   bool try_lock() _NOEXCEPT;
230   void unlock() _NOEXCEPT;
232   typedef __libcpp_recursive_mutex_t* native_handle_type;
234   _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; }
237 class _LIBCPP_EXPORTED_FROM_ABI timed_mutex {
238   mutex __m_;
239   condition_variable __cv_;
240   bool __locked_;
242 public:
243   timed_mutex();
244   ~timed_mutex();
246   timed_mutex(const timed_mutex&)            = delete;
247   timed_mutex& operator=(const timed_mutex&) = delete;
249 public:
250   void lock();
251   bool try_lock() _NOEXCEPT;
252   template <class _Rep, class _Period>
253   _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
254     return try_lock_until(chrono::steady_clock::now() + __d);
255   }
256   template <class _Clock, class _Duration>
257   _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
258   try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
259   void unlock() _NOEXCEPT;
262 template <class _Clock, class _Duration>
263 bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
264   using namespace chrono;
265   unique_lock<mutex> __lk(__m_);
266   bool __no_timeout = _Clock::now() < __t;
267   while (__no_timeout && __locked_)
268     __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
269   if (!__locked_) {
270     __locked_ = true;
271     return true;
272   }
273   return false;
276 class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex {
277   mutex __m_;
278   condition_variable __cv_;
279   size_t __count_;
280   __thread_id __id_;
282 public:
283   recursive_timed_mutex();
284   ~recursive_timed_mutex();
286   recursive_timed_mutex(const recursive_timed_mutex&)            = delete;
287   recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
289   void lock();
290   bool try_lock() _NOEXCEPT;
291   template <class _Rep, class _Period>
292   _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
293     return try_lock_until(chrono::steady_clock::now() + __d);
294   }
295   template <class _Clock, class _Duration>
296   _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
297   try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
298   void unlock() _NOEXCEPT;
301 template <class _Clock, class _Duration>
302 bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
303   using namespace chrono;
304   __thread_id __id = this_thread::get_id();
305   unique_lock<mutex> __lk(__m_);
306   if (__id == __id_) {
307     if (__count_ == numeric_limits<size_t>::max())
308       return false;
309     ++__count_;
310     return true;
311   }
312   bool __no_timeout = _Clock::now() < __t;
313   while (__no_timeout && __count_ != 0)
314     __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
315   if (__count_ == 0) {
316     __count_ = 1;
317     __id_    = __id;
318     return true;
319   }
320   return false;
323 template <class _L0, class _L1>
324 _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) {
325   unique_lock<_L0> __u0(__l0, try_to_lock_t());
326   if (__u0.owns_lock()) {
327     if (__l1.try_lock()) {
328       __u0.release();
329       return -1;
330     } else
331       return 1;
332   }
333   return 0;
336 #  ifndef _LIBCPP_CXX03_LANG
338 template <class _L0, class _L1, class _L2, class... _L3>
339 _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
340   int __r = 0;
341   unique_lock<_L0> __u0(__l0, try_to_lock);
342   if (__u0.owns_lock()) {
343     __r = std::try_lock(__l1, __l2, __l3...);
344     if (__r == -1)
345       __u0.release();
346     else
347       ++__r;
348   }
349   return __r;
352 #  endif // _LIBCPP_CXX03_LANG
354 template <class _L0, class _L1>
355 _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) {
356   while (true) {
357     {
358       unique_lock<_L0> __u0(__l0);
359       if (__l1.try_lock()) {
360         __u0.release();
361         break;
362       }
363     }
364     __libcpp_thread_yield();
365     {
366       unique_lock<_L1> __u1(__l1);
367       if (__l0.try_lock()) {
368         __u1.release();
369         break;
370       }
371     }
372     __libcpp_thread_yield();
373   }
376 #  ifndef _LIBCPP_CXX03_LANG
378 template <class _L0, class _L1, class _L2, class... _L3>
379 void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
380   while (true) {
381     switch (__i) {
382     case 0: {
383       unique_lock<_L0> __u0(__l0);
384       __i = std::try_lock(__l1, __l2, __l3...);
385       if (__i == -1) {
386         __u0.release();
387         return;
388       }
389     }
390       ++__i;
391       __libcpp_thread_yield();
392       break;
393     case 1: {
394       unique_lock<_L1> __u1(__l1);
395       __i = std::try_lock(__l2, __l3..., __l0);
396       if (__i == -1) {
397         __u1.release();
398         return;
399       }
400     }
401       if (__i == sizeof...(_L3) + 1)
402         __i = 0;
403       else
404         __i += 2;
405       __libcpp_thread_yield();
406       break;
407     default:
408       std::__lock_first(__i - 2, __l2, __l3..., __l0, __l1);
409       return;
410     }
411   }
414 template <class _L0, class _L1, class _L2, class... _L3>
415 inline _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
416   std::__lock_first(0, __l0, __l1, __l2, __l3...);
419 #  endif // _LIBCPP_CXX03_LANG
421 #  if _LIBCPP_STD_VER >= 17
422 template <class... _Mutexes>
423 class _LIBCPP_TEMPLATE_VIS scoped_lock;
425 template <>
426 class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
427 public:
428   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock() {}
429   ~scoped_lock() = default;
431   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {}
433   scoped_lock(scoped_lock const&)            = delete;
434   scoped_lock& operator=(scoped_lock const&) = delete;
437 template <class _Mutex>
438 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
439 public:
440   typedef _Mutex mutex_type;
442 private:
443   mutex_type& __m_;
445 public:
446   [[nodiscard]]
447   _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
448       : __m_(__m) {
449     __m_.lock();
450   }
452   ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
454   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
455       _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
456       : __m_(__m) {}
458   scoped_lock(scoped_lock const&)            = delete;
459   scoped_lock& operator=(scoped_lock const&) = delete;
462 template <class... _MArgs>
463 class _LIBCPP_TEMPLATE_VIS scoped_lock {
464   static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
465   typedef tuple<_MArgs&...> _MutexTuple;
467 public:
468   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) {
469     std::lock(__margs...);
470   }
472   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {}
474   _LIBCPP_HIDE_FROM_ABI ~scoped_lock() {
475     typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
476     __unlock_unpack(_Indices{}, __t_);
477   }
479   scoped_lock(scoped_lock const&)            = delete;
480   scoped_lock& operator=(scoped_lock const&) = delete;
482 private:
483   template <size_t... _Indx>
484   _LIBCPP_HIDE_FROM_ABI static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
485     (std::get<_Indx>(__mt).unlock(), ...);
486   }
488   _MutexTuple __t_;
490 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock);
492 #  endif // _LIBCPP_STD_VER >= 17
493 #endif   // _LIBCPP_HAS_THREADS
495 _LIBCPP_END_NAMESPACE_STD
497 _LIBCPP_POP_MACROS
499 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
500 #  include <atomic>
501 #  include <concepts>
502 #  include <cstdlib>
503 #  include <cstring>
504 #  include <ctime>
505 #  include <initializer_list>
506 #  include <iosfwd>
507 #  include <new>
508 #  include <stdexcept>
509 #  include <system_error>
510 #  include <type_traits>
511 #  include <typeinfo>
512 #endif
514 #endif // _LIBCPP_MUTEX