]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libc++/include/__mutex_base
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / libc++ / include / __mutex_base
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_BASE
11 #define _LIBCPP___MUTEX_BASE
12
13 #include <__config>
14 #include <chrono>
15 #include <system_error>
16 #include <__threading_support>
17
18
19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #pragma GCC system_header
21 #endif
22
23 _LIBCPP_PUSH_MACROS
24 #include <__undef_macros>
25
26
27 _LIBCPP_BEGIN_NAMESPACE_STD
28
29 #ifndef _LIBCPP_HAS_NO_THREADS
30
31 #ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
32 #  ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
33 #    define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
34 #  else
35 #    define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
36 #  endif
37 #endif  // _LIBCPP_THREAD_SAFETY_ANNOTATION
38
39
40 class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
41 {
42     __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
43
44 public:
45     _LIBCPP_INLINE_VISIBILITY
46     _LIBCPP_CONSTEXPR mutex() = default;
47
48     mutex(const mutex&) = delete;
49     mutex& operator=(const mutex&) = delete;
50
51 #if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION)
52     ~mutex() = default;
53 #else
54     ~mutex() _NOEXCEPT;
55 #endif
56
57     void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
58     bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
59     void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
60
61     typedef __libcpp_mutex_t* native_handle_type;
62     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
63 };
64
65 static_assert(is_nothrow_default_constructible<mutex>::value,
66               "the default constructor for std::mutex must be nothrow");
67
68 struct _LIBCPP_TYPE_VIS defer_lock_t {};
69 struct _LIBCPP_TYPE_VIS try_to_lock_t {};
70 struct _LIBCPP_TYPE_VIS adopt_lock_t {};
71
72 #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
73
74 extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t  defer_lock;
75 extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock;
76 extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t  adopt_lock;
77
78 #else
79
80 /* _LIBCPP_INLINE_VAR */ constexpr defer_lock_t  defer_lock  = defer_lock_t();
81 /* _LIBCPP_INLINE_VAR */ constexpr try_to_lock_t try_to_lock = try_to_lock_t();
82 /* _LIBCPP_INLINE_VAR */ constexpr adopt_lock_t  adopt_lock  = adopt_lock_t();
83
84 #endif
85
86 template <class _Mutex>
87 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
88 lock_guard
89 {
90 public:
91     typedef _Mutex mutex_type;
92
93 private:
94     mutex_type& __m_;
95 public:
96
97     _LIBCPP_INLINE_VISIBILITY
98     explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
99         : __m_(__m) {__m_.lock();}
100     _LIBCPP_INLINE_VISIBILITY
101     lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
102         : __m_(__m) {}
103     _LIBCPP_INLINE_VISIBILITY
104     ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
105
106 private:
107     lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE;
108     lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE;
109 };
110
111 template <class _Mutex>
112 class _LIBCPP_TEMPLATE_VIS unique_lock
113 {
114 public:
115     typedef _Mutex mutex_type;
116
117 private:
118     mutex_type* __m_;
119     bool __owns_;
120
121 public:
122     _LIBCPP_INLINE_VISIBILITY
123     unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
124     _LIBCPP_INLINE_VISIBILITY
125     explicit unique_lock(mutex_type& __m)
126         : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();}
127     _LIBCPP_INLINE_VISIBILITY
128     unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
129         : __m_(_VSTD::addressof(__m)), __owns_(false) {}
130     _LIBCPP_INLINE_VISIBILITY
131     unique_lock(mutex_type& __m, try_to_lock_t)
132         : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {}
133     _LIBCPP_INLINE_VISIBILITY
134     unique_lock(mutex_type& __m, adopt_lock_t)
135         : __m_(_VSTD::addressof(__m)), __owns_(true) {}
136     template <class _Clock, class _Duration>
137     _LIBCPP_INLINE_VISIBILITY
138         unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
139             : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
140     template <class _Rep, class _Period>
141     _LIBCPP_INLINE_VISIBILITY
142         unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
143             : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
144     _LIBCPP_INLINE_VISIBILITY
145     ~unique_lock()
146     {
147         if (__owns_)
148             __m_->unlock();
149     }
150
151 private:
152     unique_lock(unique_lock const&); // = delete;
153     unique_lock& operator=(unique_lock const&); // = delete;
154
155 public:
156 #ifndef _LIBCPP_CXX03_LANG
157     _LIBCPP_INLINE_VISIBILITY
158     unique_lock(unique_lock&& __u) _NOEXCEPT
159         : __m_(__u.__m_), __owns_(__u.__owns_)
160         {__u.__m_ = nullptr; __u.__owns_ = false;}
161     _LIBCPP_INLINE_VISIBILITY
162     unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
163         {
164             if (__owns_)
165                 __m_->unlock();
166             __m_ = __u.__m_;
167             __owns_ = __u.__owns_;
168             __u.__m_ = nullptr;
169             __u.__owns_ = false;
170             return *this;
171         }
172
173 #endif  // _LIBCPP_CXX03_LANG
174
175     void lock();
176     bool try_lock();
177
178     template <class _Rep, class _Period>
179         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
180     template <class _Clock, class _Duration>
181         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
182
183     void unlock();
184
185     _LIBCPP_INLINE_VISIBILITY
186     void swap(unique_lock& __u) _NOEXCEPT
187     {
188         _VSTD::swap(__m_, __u.__m_);
189         _VSTD::swap(__owns_, __u.__owns_);
190     }
191     _LIBCPP_INLINE_VISIBILITY
192     mutex_type* release() _NOEXCEPT
193     {
194         mutex_type* __m = __m_;
195         __m_ = nullptr;
196         __owns_ = false;
197         return __m;
198     }
199
200     _LIBCPP_INLINE_VISIBILITY
201     bool owns_lock() const _NOEXCEPT {return __owns_;}
202     _LIBCPP_INLINE_VISIBILITY
203     _LIBCPP_EXPLICIT
204         operator bool () const _NOEXCEPT {return __owns_;}
205     _LIBCPP_INLINE_VISIBILITY
206     mutex_type* mutex() const _NOEXCEPT {return __m_;}
207 };
208
209 template <class _Mutex>
210 void
211 unique_lock<_Mutex>::lock()
212 {
213     if (__m_ == nullptr)
214         __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
215     if (__owns_)
216         __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
217     __m_->lock();
218     __owns_ = true;
219 }
220
221 template <class _Mutex>
222 bool
223 unique_lock<_Mutex>::try_lock()
224 {
225     if (__m_ == nullptr)
226         __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
227     if (__owns_)
228         __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
229     __owns_ = __m_->try_lock();
230     return __owns_;
231 }
232
233 template <class _Mutex>
234 template <class _Rep, class _Period>
235 bool
236 unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
237 {
238     if (__m_ == nullptr)
239         __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
240     if (__owns_)
241         __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
242     __owns_ = __m_->try_lock_for(__d);
243     return __owns_;
244 }
245
246 template <class _Mutex>
247 template <class _Clock, class _Duration>
248 bool
249 unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
250 {
251     if (__m_ == nullptr)
252         __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
253     if (__owns_)
254         __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
255     __owns_ = __m_->try_lock_until(__t);
256     return __owns_;
257 }
258
259 template <class _Mutex>
260 void
261 unique_lock<_Mutex>::unlock()
262 {
263     if (!__owns_)
264         __throw_system_error(EPERM, "unique_lock::unlock: not locked");
265     __m_->unlock();
266     __owns_ = false;
267 }
268
269 template <class _Mutex>
270 inline _LIBCPP_INLINE_VISIBILITY
271 void
272 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
273     {__x.swap(__y);}
274
275 //enum class cv_status
276 _LIBCPP_DECLARE_STRONG_ENUM(cv_status)
277 {
278     no_timeout,
279     timeout
280 };
281 _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
282
283 class _LIBCPP_TYPE_VIS condition_variable
284 {
285     __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
286 public:
287     _LIBCPP_INLINE_VISIBILITY
288     _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
289
290 #ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
291     ~condition_variable() = default;
292 #else
293     ~condition_variable();
294 #endif
295
296     condition_variable(const condition_variable&) = delete;
297     condition_variable& operator=(const condition_variable&) = delete;
298
299     void notify_one() _NOEXCEPT;
300     void notify_all() _NOEXCEPT;
301
302     void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
303     template <class _Predicate>
304         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
305         void wait(unique_lock<mutex>& __lk, _Predicate __pred);
306
307     template <class _Clock, class _Duration>
308         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
309         cv_status
310         wait_until(unique_lock<mutex>& __lk,
311                    const chrono::time_point<_Clock, _Duration>& __t);
312
313     template <class _Clock, class _Duration, class _Predicate>
314         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
315         bool
316         wait_until(unique_lock<mutex>& __lk,
317                    const chrono::time_point<_Clock, _Duration>& __t,
318                    _Predicate __pred);
319
320     template <class _Rep, class _Period>
321         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
322         cv_status
323         wait_for(unique_lock<mutex>& __lk,
324                  const chrono::duration<_Rep, _Period>& __d);
325
326     template <class _Rep, class _Period, class _Predicate>
327         bool
328         _LIBCPP_INLINE_VISIBILITY
329         wait_for(unique_lock<mutex>& __lk,
330                  const chrono::duration<_Rep, _Period>& __d,
331                  _Predicate __pred);
332
333     typedef __libcpp_condvar_t* native_handle_type;
334     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
335
336 private:
337     void __do_timed_wait(unique_lock<mutex>& __lk,
338        chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
339 };
340 #endif // !_LIBCPP_HAS_NO_THREADS
341
342 template <class _To, class _Rep, class _Period>
343 inline _LIBCPP_INLINE_VISIBILITY
344 typename enable_if
345 <
346     chrono::__is_duration<_To>::value,
347     _To
348 >::type
349 __ceil(chrono::duration<_Rep, _Period> __d)
350 {
351     using namespace chrono;
352     _To __r = duration_cast<_To>(__d);
353     if (__r < __d)
354         ++__r;
355     return __r;
356 }
357
358 #ifndef _LIBCPP_HAS_NO_THREADS
359 template <class _Predicate>
360 void
361 condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
362 {
363     while (!__pred())
364         wait(__lk);
365 }
366
367 template <class _Clock, class _Duration>
368 cv_status
369 condition_variable::wait_until(unique_lock<mutex>& __lk,
370                                const chrono::time_point<_Clock, _Duration>& __t)
371 {
372     using namespace chrono;
373     wait_for(__lk, __t - _Clock::now());
374     return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
375 }
376
377 template <class _Clock, class _Duration, class _Predicate>
378 bool
379 condition_variable::wait_until(unique_lock<mutex>& __lk,
380                    const chrono::time_point<_Clock, _Duration>& __t,
381                    _Predicate __pred)
382 {
383     while (!__pred())
384     {
385         if (wait_until(__lk, __t) == cv_status::timeout)
386             return __pred();
387     }
388     return true;
389 }
390
391 template <class _Rep, class _Period>
392 cv_status
393 condition_variable::wait_for(unique_lock<mutex>& __lk,
394                              const chrono::duration<_Rep, _Period>& __d)
395 {
396     using namespace chrono;
397     if (__d <= __d.zero())
398         return cv_status::timeout;
399     typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
400     typedef time_point<system_clock, nanoseconds> __sys_tpi;
401     __sys_tpf _Max = __sys_tpi::max();
402     steady_clock::time_point __c_now = steady_clock::now();
403     system_clock::time_point __s_now = system_clock::now();
404     if (_Max - __d > __s_now)
405         __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
406     else
407         __do_timed_wait(__lk, __sys_tpi::max());
408     return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
409                                                  cv_status::timeout;
410 }
411
412 template <class _Rep, class _Period, class _Predicate>
413 inline
414 bool
415 condition_variable::wait_for(unique_lock<mutex>& __lk,
416                              const chrono::duration<_Rep, _Period>& __d,
417                              _Predicate __pred)
418 {
419     return wait_until(__lk, chrono::steady_clock::now() + __d,
420                       _VSTD::move(__pred));
421 }
422
423 #endif // !_LIBCPP_HAS_NO_THREADS
424
425 _LIBCPP_END_NAMESPACE_STD
426
427 _LIBCPP_POP_MACROS
428
429 #endif  // _LIBCPP___MUTEX_BASE