xref: /freebsd/contrib/llvm-project/libcxx/include/__cxx03/mutex (revision 700637cbb5e582861067a11aaca4d053546871d2)
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___CXX03_MUTEX
11#define _LIBCPP___CXX03_MUTEX
12
13/*
14    mutex synopsis
15
16namespace std
17{
18
19class mutex
20{
21public:
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
36class recursive_mutex
37{
38public:
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
53class timed_mutex
54{
55public:
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
71class recursive_timed_mutex
72{
73public:
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
89struct defer_lock_t { explicit defer_lock_t() = default; };
90struct try_to_lock_t { explicit try_to_lock_t() = default; };
91struct adopt_lock_t { explicit adopt_lock_t() = default; };
92
93inline constexpr defer_lock_t  defer_lock{};
94inline constexpr try_to_lock_t try_to_lock{};
95inline constexpr adopt_lock_t  adopt_lock{};
96
97template <class Mutex>
98class lock_guard
99{
100public:
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
111template <class... MutexTypes>
112class scoped_lock // C++17
113{
114public:
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;
122private:
123    tuple<MutexTypes&...> pm; // exposition only
124};
125
126template <class Mutex>
127class unique_lock
128{
129public:
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
166template <class Mutex>
167  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
168
169template <class L1, class L2, class... L3>
170  int try_lock(L1&, L2&, L3&...);
171template <class L1, class L2, class... L3>
172  void lock(L1&, L2&, L3&...);
173
174struct 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
182template<class Callable, class ...Args>
183  void call_once(once_flag& flag, Callable&& func, Args&&... args);
184
185}  // std
186
187*/
188
189#include <__cxx03/__chrono/steady_clock.h>
190#include <__cxx03/__chrono/time_point.h>
191#include <__cxx03/__condition_variable/condition_variable.h>
192#include <__cxx03/__config>
193#include <__cxx03/__memory/shared_ptr.h>
194#include <__cxx03/__mutex/lock_guard.h>
195#include <__cxx03/__mutex/mutex.h>
196#include <__cxx03/__mutex/once_flag.h>
197#include <__cxx03/__mutex/tag_types.h>
198#include <__cxx03/__mutex/unique_lock.h>
199#include <__cxx03/__thread/id.h>
200#include <__cxx03/__thread/support.h>
201#include <__cxx03/__utility/forward.h>
202#include <__cxx03/cstddef>
203#include <__cxx03/limits>
204#include <__cxx03/version>
205
206#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
207#  pragma GCC system_header
208#endif
209
210_LIBCPP_PUSH_MACROS
211#include <__cxx03/__undef_macros>
212
213_LIBCPP_BEGIN_NAMESPACE_STD
214
215#ifndef _LIBCPP_HAS_NO_THREADS
216
217class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex {
218  __libcpp_recursive_mutex_t __m_;
219
220public:
221  recursive_mutex();
222  ~recursive_mutex();
223
224  recursive_mutex(const recursive_mutex&)            = delete;
225  recursive_mutex& operator=(const recursive_mutex&) = delete;
226
227  void lock();
228  bool try_lock() _NOEXCEPT;
229  void unlock() _NOEXCEPT;
230
231  typedef __libcpp_recursive_mutex_t* native_handle_type;
232
233  _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; }
234};
235
236class _LIBCPP_EXPORTED_FROM_ABI timed_mutex {
237  mutex __m_;
238  condition_variable __cv_;
239  bool __locked_;
240
241public:
242  timed_mutex();
243  ~timed_mutex();
244
245  timed_mutex(const timed_mutex&)            = delete;
246  timed_mutex& operator=(const timed_mutex&) = delete;
247
248public:
249  void lock();
250  bool try_lock() _NOEXCEPT;
251  template <class _Rep, class _Period>
252  _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
253    return try_lock_until(chrono::steady_clock::now() + __d);
254  }
255  template <class _Clock, class _Duration>
256  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
257  try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
258  void unlock() _NOEXCEPT;
259};
260
261template <class _Clock, class _Duration>
262bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
263  using namespace chrono;
264  unique_lock<mutex> __lk(__m_);
265  bool __no_timeout = _Clock::now() < __t;
266  while (__no_timeout && __locked_)
267    __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
268  if (!__locked_) {
269    __locked_ = true;
270    return true;
271  }
272  return false;
273}
274
275class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex {
276  mutex __m_;
277  condition_variable __cv_;
278  size_t __count_;
279  __thread_id __id_;
280
281public:
282  recursive_timed_mutex();
283  ~recursive_timed_mutex();
284
285  recursive_timed_mutex(const recursive_timed_mutex&)            = delete;
286  recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
287
288  void lock();
289  bool try_lock() _NOEXCEPT;
290  template <class _Rep, class _Period>
291  _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
292    return try_lock_until(chrono::steady_clock::now() + __d);
293  }
294  template <class _Clock, class _Duration>
295  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
296  try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
297  void unlock() _NOEXCEPT;
298};
299
300template <class _Clock, class _Duration>
301bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
302  using namespace chrono;
303  __thread_id __id = this_thread::get_id();
304  unique_lock<mutex> __lk(__m_);
305  if (__id == __id_) {
306    if (__count_ == numeric_limits<size_t>::max())
307      return false;
308    ++__count_;
309    return true;
310  }
311  bool __no_timeout = _Clock::now() < __t;
312  while (__no_timeout && __count_ != 0)
313    __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
314  if (__count_ == 0) {
315    __count_ = 1;
316    __id_    = __id;
317    return true;
318  }
319  return false;
320}
321
322template <class _L0, class _L1>
323_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) {
324  unique_lock<_L0> __u0(__l0, try_to_lock_t());
325  if (__u0.owns_lock()) {
326    if (__l1.try_lock()) {
327      __u0.release();
328      return -1;
329    } else
330      return 1;
331  }
332  return 0;
333}
334
335template <class _L0, class _L1>
336_LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) {
337  while (true) {
338    {
339      unique_lock<_L0> __u0(__l0);
340      if (__l1.try_lock()) {
341        __u0.release();
342        break;
343      }
344    }
345    __libcpp_thread_yield();
346    {
347      unique_lock<_L1> __u1(__l1);
348      if (__l0.try_lock()) {
349        __u1.release();
350        break;
351      }
352    }
353    __libcpp_thread_yield();
354  }
355}
356#endif   // !_LIBCPP_HAS_NO_THREADS
357
358_LIBCPP_END_NAMESPACE_STD
359
360_LIBCPP_POP_MACROS
361
362#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES)
363#  include <__cxx03/atomic>
364#  include <__cxx03/cstdlib>
365#  include <__cxx03/cstring>
366#  include <__cxx03/ctime>
367#  include <__cxx03/iosfwd>
368#  include <__cxx03/new>
369#  include <__cxx03/stdexcept>
370#  include <__cxx03/system_error>
371#  include <__cxx03/type_traits>
372#  include <__cxx03/typeinfo>
373#endif
374
375#endif // _LIBCPP___CXX03_MUTEX
376