]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libc++/include/__mutex_base
MFV r316928: 7256 low probability race in zfs_get_data
[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 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #pragma GCC system_header
21 #endif
22
23 _LIBCPP_BEGIN_NAMESPACE_STD
24
25 #ifndef _LIBCPP_HAS_NO_THREADS
26
27 #ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
28 #  ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
29 #    define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
30 #  else
31 #    define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
32 #  endif
33 #endif  // _LIBCPP_THREAD_SAFETY_ANNOTATION
34
35 class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
36 {
37 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
38     __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
39 #else
40     __libcpp_mutex_t __m_;
41 #endif
42
43 public:
44     _LIBCPP_INLINE_VISIBILITY
45 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
46     constexpr mutex() _NOEXCEPT = default;
47 #else
48     mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;}
49 #endif
50     ~mutex();
51
52 private:
53     mutex(const mutex&);// = delete;
54     mutex& operator=(const mutex&);// = delete;
55
56 public:
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 struct _LIBCPP_TYPE_VIS defer_lock_t {};
66 struct _LIBCPP_TYPE_VIS try_to_lock_t {};
67 struct _LIBCPP_TYPE_VIS adopt_lock_t {};
68
69 #if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
70
71 extern const defer_lock_t  defer_lock;
72 extern const try_to_lock_t try_to_lock;
73 extern const adopt_lock_t  adopt_lock;
74
75 #else
76
77 constexpr defer_lock_t  defer_lock  = defer_lock_t();
78 constexpr try_to_lock_t try_to_lock = try_to_lock_t();
79 constexpr adopt_lock_t  adopt_lock  = adopt_lock_t();
80
81 #endif
82
83
84 // Forward declare lock_guard as a variadic template even in C++03 to keep
85 // the mangling consistent between dialects.
86 #if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD)
87 template <class ..._Mutexes>
88 class _LIBCPP_TEMPLATE_VIS lock_guard;
89 #endif
90
91 template <class _Mutex>
92 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
93 #if !defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD)
94 lock_guard
95 #else
96 lock_guard<_Mutex>
97 #endif
98 {
99 public:
100     typedef _Mutex mutex_type;
101
102 private:
103     mutex_type& __m_;
104 public:
105
106     _LIBCPP_INLINE_VISIBILITY
107     explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
108         : __m_(__m) {__m_.lock();}
109     _LIBCPP_INLINE_VISIBILITY
110     lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
111         : __m_(__m) {}
112     _LIBCPP_INLINE_VISIBILITY
113     ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
114
115 private:
116     lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE;
117     lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE;
118 };
119
120 template <class _Mutex>
121 class _LIBCPP_TEMPLATE_VIS unique_lock
122 {
123 public:
124     typedef _Mutex mutex_type;
125
126 private:
127     mutex_type* __m_;
128     bool __owns_;
129
130 public:
131     _LIBCPP_INLINE_VISIBILITY
132     unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
133     _LIBCPP_INLINE_VISIBILITY
134     explicit unique_lock(mutex_type& __m)
135         : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();}
136     _LIBCPP_INLINE_VISIBILITY
137     unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
138         : __m_(_VSTD::addressof(__m)), __owns_(false) {}
139     _LIBCPP_INLINE_VISIBILITY
140     unique_lock(mutex_type& __m, try_to_lock_t)
141         : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {}
142     _LIBCPP_INLINE_VISIBILITY
143     unique_lock(mutex_type& __m, adopt_lock_t)
144         : __m_(_VSTD::addressof(__m)), __owns_(true) {}
145     template <class _Clock, class _Duration>
146     _LIBCPP_INLINE_VISIBILITY
147         unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
148             : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
149     template <class _Rep, class _Period>
150     _LIBCPP_INLINE_VISIBILITY
151         unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
152             : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
153     _LIBCPP_INLINE_VISIBILITY
154     ~unique_lock()
155     {
156         if (__owns_)
157             __m_->unlock();
158     }
159
160 private:
161     unique_lock(unique_lock const&); // = delete;
162     unique_lock& operator=(unique_lock const&); // = delete;
163
164 public:
165 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
166     _LIBCPP_INLINE_VISIBILITY
167     unique_lock(unique_lock&& __u) _NOEXCEPT
168         : __m_(__u.__m_), __owns_(__u.__owns_)
169         {__u.__m_ = nullptr; __u.__owns_ = false;}
170     _LIBCPP_INLINE_VISIBILITY
171     unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
172         {
173             if (__owns_)
174                 __m_->unlock();
175             __m_ = __u.__m_;
176             __owns_ = __u.__owns_;
177             __u.__m_ = nullptr;
178             __u.__owns_ = false;
179             return *this;
180         }
181
182 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
183
184     void lock();
185     bool try_lock();
186
187     template <class _Rep, class _Period>
188         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
189     template <class _Clock, class _Duration>
190         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
191
192     void unlock();
193
194     _LIBCPP_INLINE_VISIBILITY
195     void swap(unique_lock& __u) _NOEXCEPT
196     {
197         _VSTD::swap(__m_, __u.__m_);
198         _VSTD::swap(__owns_, __u.__owns_);
199     }
200     _LIBCPP_INLINE_VISIBILITY
201     mutex_type* release() _NOEXCEPT
202     {
203         mutex_type* __m = __m_;
204         __m_ = nullptr;
205         __owns_ = false;
206         return __m;
207     }
208
209     _LIBCPP_INLINE_VISIBILITY
210     bool owns_lock() const _NOEXCEPT {return __owns_;}
211     _LIBCPP_INLINE_VISIBILITY
212     _LIBCPP_EXPLICIT
213         operator bool () const _NOEXCEPT {return __owns_;}
214     _LIBCPP_INLINE_VISIBILITY
215     mutex_type* mutex() const _NOEXCEPT {return __m_;}
216 };
217
218 template <class _Mutex>
219 void
220 unique_lock<_Mutex>::lock()
221 {
222     if (__m_ == nullptr)
223         __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
224     if (__owns_)
225         __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
226     __m_->lock();
227     __owns_ = true;
228 }
229
230 template <class _Mutex>
231 bool
232 unique_lock<_Mutex>::try_lock()
233 {
234     if (__m_ == nullptr)
235         __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
236     if (__owns_)
237         __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
238     __owns_ = __m_->try_lock();
239     return __owns_;
240 }
241
242 template <class _Mutex>
243 template <class _Rep, class _Period>
244 bool
245 unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
246 {
247     if (__m_ == nullptr)
248         __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
249     if (__owns_)
250         __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
251     __owns_ = __m_->try_lock_for(__d);
252     return __owns_;
253 }
254
255 template <class _Mutex>
256 template <class _Clock, class _Duration>
257 bool
258 unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
259 {
260     if (__m_ == nullptr)
261         __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
262     if (__owns_)
263         __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
264     __owns_ = __m_->try_lock_until(__t);
265     return __owns_;
266 }
267
268 template <class _Mutex>
269 void
270 unique_lock<_Mutex>::unlock()
271 {
272     if (!__owns_)
273         __throw_system_error(EPERM, "unique_lock::unlock: not locked");
274     __m_->unlock();
275     __owns_ = false;
276 }
277
278 template <class _Mutex>
279 inline _LIBCPP_INLINE_VISIBILITY
280 void
281 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
282     {__x.swap(__y);}
283
284 //enum class cv_status
285 _LIBCPP_DECLARE_STRONG_ENUM(cv_status)
286 {
287     no_timeout,
288     timeout
289 };
290 _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
291
292 class _LIBCPP_TYPE_VIS condition_variable
293 {
294 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
295     __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
296 #else
297     __libcpp_condvar_t __cv_;
298 #endif
299
300 public:
301     _LIBCPP_INLINE_VISIBILITY
302 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
303     constexpr condition_variable() _NOEXCEPT = default;
304 #else
305     condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;}
306 #endif
307     ~condition_variable();
308
309 private:
310     condition_variable(const condition_variable&); // = delete;
311     condition_variable& operator=(const condition_variable&); // = delete;
312
313 public:
314     void notify_one() _NOEXCEPT;
315     void notify_all() _NOEXCEPT;
316
317     void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
318     template <class _Predicate>
319         void wait(unique_lock<mutex>& __lk, _Predicate __pred);
320
321     template <class _Clock, class _Duration>
322         cv_status
323         wait_until(unique_lock<mutex>& __lk,
324                    const chrono::time_point<_Clock, _Duration>& __t);
325
326     template <class _Clock, class _Duration, class _Predicate>
327         bool
328         wait_until(unique_lock<mutex>& __lk,
329                    const chrono::time_point<_Clock, _Duration>& __t,
330                    _Predicate __pred);
331
332     template <class _Rep, class _Period>
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 #endif  // _LIBCPP___MUTEX_BASE