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