Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / include / mutex
blobbdf1742dfcfe140bee98231ebe2e47f4aa58a204
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 <__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>
210 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
211 #  pragma GCC system_header
212 #endif
214 _LIBCPP_PUSH_MACROS
215 #include <__undef_macros>
218 _LIBCPP_BEGIN_NAMESPACE_STD
220 #ifndef _LIBCPP_HAS_NO_THREADS
222 class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex
224     __libcpp_recursive_mutex_t __m_;
226 public:
227     recursive_mutex();
228     ~recursive_mutex();
230     recursive_mutex(const recursive_mutex&) = delete;
231     recursive_mutex& operator=(const recursive_mutex&) = delete;
233     void lock();
234     bool try_lock() _NOEXCEPT;
235     void unlock()  _NOEXCEPT;
237     typedef __libcpp_recursive_mutex_t* native_handle_type;
239     _LIBCPP_INLINE_VISIBILITY
240     native_handle_type native_handle() {return &__m_;}
243 class _LIBCPP_EXPORTED_FROM_ABI timed_mutex
245     mutex              __m_;
246     condition_variable __cv_;
247     bool               __locked_;
248 public:
249      timed_mutex();
250      ~timed_mutex();
252     timed_mutex(const timed_mutex&) = delete;
253     timed_mutex& operator=(const timed_mutex&) = delete;
255 public:
256     void lock();
257     bool try_lock() _NOEXCEPT;
258     template <class _Rep, class _Period>
259         _LIBCPP_INLINE_VISIBILITY
260         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
261             {return try_lock_until(chrono::steady_clock::now() + __d);}
262     template <class _Clock, class _Duration>
263         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
264         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
265     void unlock() _NOEXCEPT;
268 template <class _Clock, class _Duration>
269 bool
270 timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
272     using namespace chrono;
273     unique_lock<mutex> __lk(__m_);
274     bool __no_timeout = _Clock::now() < __t;
275     while (__no_timeout && __locked_)
276         __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
277     if (!__locked_)
278     {
279         __locked_ = true;
280         return true;
281     }
282     return false;
285 class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex
287     mutex              __m_;
288     condition_variable __cv_;
289     size_t             __count_;
290     __thread_id        __id_;
291 public:
292     recursive_timed_mutex();
293     ~recursive_timed_mutex();
295     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
296     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
298     void lock();
299     bool try_lock() _NOEXCEPT;
300     template <class _Rep, class _Period>
301         _LIBCPP_INLINE_VISIBILITY
302         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
303             {return try_lock_until(chrono::steady_clock::now() + __d);}
304     template <class _Clock, class _Duration>
305         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
306         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
307     void unlock() _NOEXCEPT;
310 template <class _Clock, class _Duration>
311 bool
312 recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
314     using namespace chrono;
315     __thread_id __id = this_thread::get_id();
316     unique_lock<mutex> __lk(__m_);
317     if (__id == __id_)
318     {
319         if (__count_ == numeric_limits<size_t>::max())
320             return false;
321         ++__count_;
322         return true;
323     }
324     bool __no_timeout = _Clock::now() < __t;
325     while (__no_timeout && __count_ != 0)
326         __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
327     if (__count_ == 0)
328     {
329         __count_ = 1;
330         __id_ = __id;
331         return true;
332     }
333     return false;
336 template <class _L0, class _L1>
337 _LIBCPP_HIDE_FROM_ABI int
338 try_lock(_L0& __l0, _L1& __l1)
340     unique_lock<_L0> __u0(__l0, try_to_lock_t());
341     if (__u0.owns_lock())
342     {
343         if (__l1.try_lock())
344         {
345             __u0.release();
346             return -1;
347         }
348         else
349             return 1;
350     }
351     return 0;
354 #ifndef _LIBCPP_CXX03_LANG
356 template <class _L0, class _L1, class _L2, class... _L3>
357 _LIBCPP_HIDE_FROM_ABI int
358 try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
360     int __r = 0;
361     unique_lock<_L0> __u0(__l0, try_to_lock);
362     if (__u0.owns_lock())
363     {
364         __r = std::try_lock(__l1, __l2, __l3...);
365         if (__r == -1)
366             __u0.release();
367         else
368             ++__r;
369     }
370     return __r;
373 #endif // _LIBCPP_CXX03_LANG
375 template <class _L0, class _L1>
376 _LIBCPP_HIDE_FROM_ABI void
377 lock(_L0& __l0, _L1& __l1)
379     while (true)
380     {
381         {
382             unique_lock<_L0> __u0(__l0);
383             if (__l1.try_lock())
384             {
385                 __u0.release();
386                 break;
387             }
388         }
389         __libcpp_thread_yield();
390         {
391             unique_lock<_L1> __u1(__l1);
392             if (__l0.try_lock())
393             {
394                 __u1.release();
395                 break;
396             }
397         }
398         __libcpp_thread_yield();
399     }
402 #ifndef _LIBCPP_CXX03_LANG
404 template <class _L0, class _L1, class _L2, class ..._L3>
405 void
406 __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
408     while (true)
409     {
410         switch (__i)
411         {
412         case 0:
413             {
414                 unique_lock<_L0> __u0(__l0);
415                 __i = std::try_lock(__l1, __l2, __l3...);
416                 if (__i == -1)
417                 {
418                     __u0.release();
419                     return;
420                 }
421             }
422             ++__i;
423             __libcpp_thread_yield();
424             break;
425         case 1:
426             {
427                 unique_lock<_L1> __u1(__l1);
428                 __i = std::try_lock(__l2, __l3..., __l0);
429                 if (__i == -1)
430                 {
431                     __u1.release();
432                     return;
433                 }
434             }
435             if (__i == sizeof...(_L3) + 1)
436                 __i = 0;
437             else
438                 __i += 2;
439             __libcpp_thread_yield();
440             break;
441         default:
442             std::__lock_first(__i - 2, __l2, __l3..., __l0, __l1);
443             return;
444         }
445     }
448 template <class _L0, class _L1, class _L2, class ..._L3>
449 inline _LIBCPP_INLINE_VISIBILITY
450 void
451 lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
453     std::__lock_first(0, __l0, __l1, __l2, __l3...);
456 template <class _L0>
457 inline _LIBCPP_INLINE_VISIBILITY
458 void __unlock(_L0& __l0) {
459     __l0.unlock();
462 template <class _L0, class _L1>
463 inline _LIBCPP_INLINE_VISIBILITY
464 void __unlock(_L0& __l0, _L1& __l1) {
465     __l0.unlock();
466     __l1.unlock();
469 template <class _L0, class _L1, class _L2, class ..._L3>
470 inline _LIBCPP_INLINE_VISIBILITY
471 void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
472     __l0.unlock();
473     __l1.unlock();
474     _VSTD::__unlock(__l2, __l3...);
477 #endif // _LIBCPP_CXX03_LANG
479 #if _LIBCPP_STD_VER >= 17
480 template <class ..._Mutexes>
481 class _LIBCPP_TEMPLATE_VIS scoped_lock;
483 template <>
484 class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
485 public:
486     explicit scoped_lock() {}
487     ~scoped_lock() = default;
489     _LIBCPP_INLINE_VISIBILITY
490     explicit scoped_lock(adopt_lock_t) {}
492     scoped_lock(scoped_lock const&) = delete;
493     scoped_lock& operator=(scoped_lock const&) = delete;
496 template <class _Mutex>
497 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
498 public:
499     typedef _Mutex  mutex_type;
500 private:
501     mutex_type& __m_;
502 public:
503     explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
504         : __m_(__m) {__m_.lock();}
506     ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
508     _LIBCPP_INLINE_VISIBILITY
509     explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
510         : __m_(__m) {}
512     scoped_lock(scoped_lock const&) = delete;
513     scoped_lock& operator=(scoped_lock const&) = delete;
516 template <class ..._MArgs>
517 class _LIBCPP_TEMPLATE_VIS scoped_lock
519     static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
520     typedef tuple<_MArgs&...> _MutexTuple;
522 public:
523     _LIBCPP_INLINE_VISIBILITY
524     explicit scoped_lock(_MArgs&... __margs)
525       : __t_(__margs...)
526     {
527         _VSTD::lock(__margs...);
528     }
530     _LIBCPP_INLINE_VISIBILITY
531     scoped_lock(adopt_lock_t, _MArgs&... __margs)
532         : __t_(__margs...)
533     {
534     }
536     _LIBCPP_INLINE_VISIBILITY
537     ~scoped_lock() {
538         typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
539         __unlock_unpack(_Indices{}, __t_);
540     }
542     scoped_lock(scoped_lock const&) = delete;
543     scoped_lock& operator=(scoped_lock const&) = delete;
545 private:
546     template <size_t ..._Indx>
547     _LIBCPP_INLINE_VISIBILITY
548     static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
549         _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...);
550     }
552     _MutexTuple __t_;
554 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock);
556 #endif // _LIBCPP_STD_VER >= 17
557 #endif // !_LIBCPP_HAS_NO_THREADS
559 _LIBCPP_END_NAMESPACE_STD
561 _LIBCPP_POP_MACROS
563 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
564 #  include <atomic>
565 #  include <concepts>
566 #  include <cstdlib>
567 #  include <cstring>
568 #  include <ctime>
569 #  include <initializer_list>
570 #  include <iosfwd>
571 #  include <new>
572 #  include <stdexcept>
573 #  include <system_error>
574 #  include <type_traits>
575 #  include <typeinfo>
576 #endif
578 #endif // _LIBCPP_MUTEX