btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / libc++ / __mutex_base
blobb019b4760d186a6055864202b204e6dbf7f009b0
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 //===----------------------------------------------------------------------===//
11 #ifndef _LIBCPP___MUTEX_BASE
12 #define _LIBCPP___MUTEX_BASE
14 #include <__config>
15 #include <chrono>
16 #include <system_error>
17 #ifndef _LIBCPP_HAS_NO_THREADS
18 #include <pthread.h>
19 #endif
21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22 #pragma GCC system_header
23 #endif
25 _LIBCPP_BEGIN_NAMESPACE_STD
27 #ifndef _LIBCPP_HAS_NO_THREADS
29 class _LIBCPP_TYPE_VIS mutex
31     pthread_mutex_t __m_;
33 public:
34     _LIBCPP_INLINE_VISIBILITY
35 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
36      constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {}
37 #else
38      mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
39 #endif
40      ~mutex();
42 private:
43     mutex(const mutex&);// = delete;
44     mutex& operator=(const mutex&);// = delete;
46 public:
47     void lock();
48     bool try_lock() _NOEXCEPT;
49     void unlock() _NOEXCEPT;
51     typedef pthread_mutex_t* native_handle_type;
52     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
55 struct _LIBCPP_TYPE_VIS defer_lock_t {};
56 struct _LIBCPP_TYPE_VIS try_to_lock_t {};
57 struct _LIBCPP_TYPE_VIS adopt_lock_t {};
59 #if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
61 extern const defer_lock_t  defer_lock;
62 extern const try_to_lock_t try_to_lock;
63 extern const adopt_lock_t  adopt_lock;
65 #else
67 constexpr defer_lock_t  defer_lock  = defer_lock_t();
68 constexpr try_to_lock_t try_to_lock = try_to_lock_t();
69 constexpr adopt_lock_t  adopt_lock  = adopt_lock_t();
71 #endif
73 template <class _Mutex>
74 class _LIBCPP_TYPE_VIS_ONLY lock_guard
76 public:
77     typedef _Mutex mutex_type;
79 private:
80     mutex_type& __m_;
81 public:
83     _LIBCPP_INLINE_VISIBILITY
84     explicit lock_guard(mutex_type& __m)
85         : __m_(__m) {__m_.lock();}
86     _LIBCPP_INLINE_VISIBILITY
87     lock_guard(mutex_type& __m, adopt_lock_t)
88         : __m_(__m) {}
89     _LIBCPP_INLINE_VISIBILITY
90     ~lock_guard() {__m_.unlock();}
92 private:
93     lock_guard(lock_guard const&);// = delete;
94     lock_guard& operator=(lock_guard const&);// = delete;
97 template <class _Mutex>
98 class _LIBCPP_TYPE_VIS_ONLY unique_lock
100 public:
101     typedef _Mutex mutex_type;
103 private:
104     mutex_type* __m_;
105     bool __owns_;
107 public:
108     _LIBCPP_INLINE_VISIBILITY
109     unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
110     _LIBCPP_INLINE_VISIBILITY
111     explicit unique_lock(mutex_type& __m)
112         : __m_(&__m), __owns_(true) {__m_->lock();}
113     _LIBCPP_INLINE_VISIBILITY
114     unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
115         : __m_(&__m), __owns_(false) {}
116     _LIBCPP_INLINE_VISIBILITY
117     unique_lock(mutex_type& __m, try_to_lock_t)
118         : __m_(&__m), __owns_(__m.try_lock()) {}
119     _LIBCPP_INLINE_VISIBILITY
120     unique_lock(mutex_type& __m, adopt_lock_t)
121         : __m_(&__m), __owns_(true) {}
122     template <class _Clock, class _Duration>
123     _LIBCPP_INLINE_VISIBILITY
124         unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
125             : __m_(&__m), __owns_(__m.try_lock_until(__t)) {}
126     template <class _Rep, class _Period>
127     _LIBCPP_INLINE_VISIBILITY
128         unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
129             : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
130     _LIBCPP_INLINE_VISIBILITY
131     ~unique_lock()
132     {
133         if (__owns_)
134             __m_->unlock();
135     }
137 private:
138     unique_lock(unique_lock const&); // = delete;
139     unique_lock& operator=(unique_lock const&); // = delete;
141 public:
142 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
143     _LIBCPP_INLINE_VISIBILITY
144     unique_lock(unique_lock&& __u) _NOEXCEPT
145         : __m_(__u.__m_), __owns_(__u.__owns_)
146         {__u.__m_ = nullptr; __u.__owns_ = false;}
147     _LIBCPP_INLINE_VISIBILITY
148     unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
149         {
150             if (__owns_)
151                 __m_->unlock();
152             __m_ = __u.__m_;
153             __owns_ = __u.__owns_;
154             __u.__m_ = nullptr;
155             __u.__owns_ = false;
156             return *this;
157         }
159 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
161     void lock();
162     bool try_lock();
164     template <class _Rep, class _Period>
165         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
166     template <class _Clock, class _Duration>
167         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
169     void unlock();
171     _LIBCPP_INLINE_VISIBILITY
172     void swap(unique_lock& __u) _NOEXCEPT
173     {
174         _VSTD::swap(__m_, __u.__m_);
175         _VSTD::swap(__owns_, __u.__owns_);
176     }
177     _LIBCPP_INLINE_VISIBILITY
178     mutex_type* release() _NOEXCEPT
179     {
180         mutex_type* __m = __m_;
181         __m_ = nullptr;
182         __owns_ = false;
183         return __m;
184     }
186     _LIBCPP_INLINE_VISIBILITY
187     bool owns_lock() const _NOEXCEPT {return __owns_;}
188     _LIBCPP_INLINE_VISIBILITY
189     _LIBCPP_EXPLICIT
190         operator bool () const _NOEXCEPT {return __owns_;}
191     _LIBCPP_INLINE_VISIBILITY
192     mutex_type* mutex() const _NOEXCEPT {return __m_;}
195 template <class _Mutex>
196 void
197 unique_lock<_Mutex>::lock()
199     if (__m_ == nullptr)
200         __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
201     if (__owns_)
202         __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
203     __m_->lock();
204     __owns_ = true;
207 template <class _Mutex>
208 bool
209 unique_lock<_Mutex>::try_lock()
211     if (__m_ == nullptr)
212         __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
213     if (__owns_)
214         __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
215     __owns_ = __m_->try_lock();
216     return __owns_;
219 template <class _Mutex>
220 template <class _Rep, class _Period>
221 bool
222 unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
224     if (__m_ == nullptr)
225         __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
226     if (__owns_)
227         __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
228     __owns_ = __m_->try_lock_for(__d);
229     return __owns_;
232 template <class _Mutex>
233 template <class _Clock, class _Duration>
234 bool
235 unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
237     if (__m_ == nullptr)
238         __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
239     if (__owns_)
240         __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
241     __owns_ = __m_->try_lock_until(__t);
242     return __owns_;
245 template <class _Mutex>
246 void
247 unique_lock<_Mutex>::unlock()
249     if (!__owns_)
250         __throw_system_error(EPERM, "unique_lock::unlock: not locked");
251     __m_->unlock();
252     __owns_ = false;
255 template <class _Mutex>
256 inline _LIBCPP_INLINE_VISIBILITY
257 void
258 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
259     {__x.swap(__y);}
261 //enum class cv_status
262 _LIBCPP_DECLARE_STRONG_ENUM(cv_status)
264     no_timeout,
265     timeout
267 _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
269 class _LIBCPP_TYPE_VIS condition_variable
271     pthread_cond_t __cv_;
272 public:
273     _LIBCPP_INLINE_VISIBILITY
274 #ifndef _LIBCPP_HAS_NO_CONSTEXPR
275     constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {}
276 #else
277     condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
278 #endif
279     ~condition_variable();
281 private:
282     condition_variable(const condition_variable&); // = delete;
283     condition_variable& operator=(const condition_variable&); // = delete;
285 public:
286     void notify_one() _NOEXCEPT;
287     void notify_all() _NOEXCEPT;
289     void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
290     template <class _Predicate>
291         void wait(unique_lock<mutex>& __lk, _Predicate __pred);
293     template <class _Clock, class _Duration>
294         cv_status
295         wait_until(unique_lock<mutex>& __lk,
296                    const chrono::time_point<_Clock, _Duration>& __t);
298     template <class _Clock, class _Duration, class _Predicate>
299         bool
300         wait_until(unique_lock<mutex>& __lk,
301                    const chrono::time_point<_Clock, _Duration>& __t,
302                    _Predicate __pred);
304     template <class _Rep, class _Period>
305         cv_status
306         wait_for(unique_lock<mutex>& __lk,
307                  const chrono::duration<_Rep, _Period>& __d);
309     template <class _Rep, class _Period, class _Predicate>
310         bool
311         _LIBCPP_INLINE_VISIBILITY
312         wait_for(unique_lock<mutex>& __lk,
313                  const chrono::duration<_Rep, _Period>& __d,
314                  _Predicate __pred);
316     typedef pthread_cond_t* native_handle_type;
317     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
319 private:
320     void __do_timed_wait(unique_lock<mutex>& __lk,
321        chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
323 #endif // !_LIBCPP_HAS_NO_THREADS
325 template <class _To, class _Rep, class _Period>
326 inline _LIBCPP_INLINE_VISIBILITY
327 typename enable_if
329     chrono::__is_duration<_To>::value,
330     _To
331 >::type
332 __ceil(chrono::duration<_Rep, _Period> __d)
334     using namespace chrono;
335     _To __r = duration_cast<_To>(__d);
336     if (__r < __d)
337         ++__r;
338     return __r;
341 #ifndef _LIBCPP_HAS_NO_THREADS
342 template <class _Predicate>
343 void
344 condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
346     while (!__pred())
347         wait(__lk);
350 template <class _Clock, class _Duration>
351 cv_status
352 condition_variable::wait_until(unique_lock<mutex>& __lk,
353                                const chrono::time_point<_Clock, _Duration>& __t)
355     using namespace chrono;
356     wait_for(__lk, __t - _Clock::now());
357     return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
360 template <class _Clock, class _Duration, class _Predicate>
361 bool
362 condition_variable::wait_until(unique_lock<mutex>& __lk,
363                    const chrono::time_point<_Clock, _Duration>& __t,
364                    _Predicate __pred)
366     while (!__pred())
367     {
368         if (wait_until(__lk, __t) == cv_status::timeout)
369             return __pred();
370     }
371     return true;
374 template <class _Rep, class _Period>
375 cv_status
376 condition_variable::wait_for(unique_lock<mutex>& __lk,
377                              const chrono::duration<_Rep, _Period>& __d)
379     using namespace chrono;
380     if (__d <= __d.zero())
381         return cv_status::timeout;
382     typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
383     typedef time_point<system_clock, nanoseconds> __sys_tpi;
384     __sys_tpf _Max = __sys_tpi::max();
385     system_clock::time_point __s_now = system_clock::now();
386     steady_clock::time_point __c_now = steady_clock::now();
387     if (_Max - __d > __s_now)
388         __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
389     else
390         __do_timed_wait(__lk, __sys_tpi::max());
391     return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
392                                                  cv_status::timeout;
395 template <class _Rep, class _Period, class _Predicate>
396 inline
397 bool
398 condition_variable::wait_for(unique_lock<mutex>& __lk,
399                              const chrono::duration<_Rep, _Period>& __d,
400                              _Predicate __pred)
402     return wait_until(__lk, chrono::steady_clock::now() + __d,
403                       _VSTD::move(__pred));
406 #endif // !_LIBCPP_HAS_NO_THREADS
408 _LIBCPP_END_NAMESPACE_STD
410 #endif  // _LIBCPP___MUTEX_BASE