[IRBuilder] Refactor FMF interface (#121657)
[llvm-project.git] / libcxx / include / mutex
blob9b128e8710aaebcedb91561c5be9caf9d90f8216
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 #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
190 #  include <__cxx03/mutex>
191 #else
192 #  include <__chrono/steady_clock.h>
193 #  include <__chrono/time_point.h>
194 #  include <__condition_variable/condition_variable.h>
195 #  include <__config>
196 #  include <__mutex/lock_guard.h>
197 #  include <__mutex/mutex.h>
198 #  include <__mutex/once_flag.h>
199 #  include <__mutex/tag_types.h>
200 #  include <__mutex/unique_lock.h>
201 #  include <__thread/id.h>
202 #  include <__thread/support.h>
203 #  include <__utility/forward.h>
204 #  include <limits>
205 #  ifndef _LIBCPP_CXX03_LANG
206 #    include <tuple>
207 #  endif
208 #  include <version>
210 #  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
211 #    pragma GCC system_header
212 #  endif
214 _LIBCPP_PUSH_MACROS
215 #  include <__undef_macros>
217 _LIBCPP_BEGIN_NAMESPACE_STD
219 #  if _LIBCPP_HAS_THREADS
221 class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex {
222   __libcpp_recursive_mutex_t __m_;
224 public:
225   recursive_mutex();
226   ~recursive_mutex();
228   recursive_mutex(const recursive_mutex&)            = delete;
229   recursive_mutex& operator=(const recursive_mutex&) = delete;
231   void lock();
232   bool try_lock() _NOEXCEPT;
233   void unlock() _NOEXCEPT;
235   typedef __libcpp_recursive_mutex_t* native_handle_type;
237   _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; }
240 class _LIBCPP_EXPORTED_FROM_ABI timed_mutex {
241   mutex __m_;
242   condition_variable __cv_;
243   bool __locked_;
245 public:
246   timed_mutex();
247   ~timed_mutex();
249   timed_mutex(const timed_mutex&)            = delete;
250   timed_mutex& operator=(const timed_mutex&) = delete;
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;
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;
279 class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex {
280   mutex __m_;
281   condition_variable __cv_;
282   size_t __count_;
283   __thread_id __id_;
285 public:
286   recursive_timed_mutex();
287   ~recursive_timed_mutex();
289   recursive_timed_mutex(const recursive_timed_mutex&)            = delete;
290   recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
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;
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;
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;
339 #    ifndef _LIBCPP_CXX03_LANG
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;
355 #    endif // _LIBCPP_CXX03_LANG
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   }
379 #    ifndef _LIBCPP_CXX03_LANG
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   }
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...);
422 #    endif // _LIBCPP_CXX03_LANG
424 #    if _LIBCPP_STD_VER >= 17
425 template <class... _Mutexes>
426 class _LIBCPP_TEMPLATE_VIS scoped_lock;
428 template <>
429 class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
430 public:
431   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock() {}
432   ~scoped_lock() = default;
434   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {}
436   scoped_lock(scoped_lock const&)            = delete;
437   scoped_lock& operator=(scoped_lock const&) = delete;
440 template <class _Mutex>
441 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
442 public:
443   typedef _Mutex mutex_type;
445 private:
446   mutex_type& __m_;
448 public:
449   [[nodiscard]]
450   _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
451       : __m_(__m) {
452     __m_.lock();
453   }
455   ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
457   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
458       _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
459       : __m_(__m) {}
461   scoped_lock(scoped_lock const&)            = delete;
462   scoped_lock& operator=(scoped_lock const&) = delete;
465 template <class... _MArgs>
466 class _LIBCPP_TEMPLATE_VIS scoped_lock {
467   static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
468   typedef tuple<_MArgs&...> _MutexTuple;
470 public:
471   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) {
472     std::lock(__margs...);
473   }
475   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {}
477   _LIBCPP_HIDE_FROM_ABI ~scoped_lock() {
478     typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
479     __unlock_unpack(_Indices{}, __t_);
480   }
482   scoped_lock(scoped_lock const&)            = delete;
483   scoped_lock& operator=(scoped_lock const&) = delete;
485 private:
486   template <size_t... _Indx>
487   _LIBCPP_HIDE_FROM_ABI static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
488     (std::get<_Indx>(__mt).unlock(), ...);
489   }
491   _MutexTuple __t_;
493 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock);
495 #    endif // _LIBCPP_STD_VER >= 17
496 #  endif   // _LIBCPP_HAS_THREADS
498 _LIBCPP_END_NAMESPACE_STD
500 _LIBCPP_POP_MACROS
502 #  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
503 #    include <atomic>
504 #    include <concepts>
505 #    include <cstdlib>
506 #    include <cstring>
507 #    include <ctime>
508 #    include <initializer_list>
509 #    include <iosfwd>
510 #    include <new>
511 #    include <stdexcept>
512 #    include <system_error>
513 #    include <type_traits>
514 #    include <typeinfo>
515 #  endif
516 #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
518 #endif // _LIBCPP_MUTEX