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
35class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
36{
37    __libcpp_mutex_t __m_;
38
39public:
40    _LIBCPP_INLINE_VISIBILITY
41#ifndef _LIBCPP_HAS_NO_CONSTEXPR
42    constexpr mutex() _NOEXCEPT : __m_(_LIBCPP_MUTEX_INITIALIZER) {}
43#else
44    mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;}
45#endif
46     ~mutex();
47
48private:
49    mutex(const mutex&);// = delete;
50    mutex& operator=(const mutex&);// = delete;
51
52public:
53    void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
54    bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
55    void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
56
57    typedef __libcpp_mutex_t* native_handle_type;
58    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
59};
60
61struct _LIBCPP_TYPE_VIS defer_lock_t {};
62struct _LIBCPP_TYPE_VIS try_to_lock_t {};
63struct _LIBCPP_TYPE_VIS adopt_lock_t {};
64
65#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
66
67extern const defer_lock_t  defer_lock;
68extern const try_to_lock_t try_to_lock;
69extern const adopt_lock_t  adopt_lock;
70
71#else
72
73constexpr defer_lock_t  defer_lock  = defer_lock_t();
74constexpr try_to_lock_t try_to_lock = try_to_lock_t();
75constexpr adopt_lock_t  adopt_lock  = adopt_lock_t();
76
77#endif
78
79
80// Forward declare lock_guard as a variadic template even in C++03 to keep
81// the mangling consistent between dialects.
82#if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD)
83template <class ..._Mutexes>
84class _LIBCPP_TYPE_VIS_ONLY lock_guard;
85#endif
86
87template <class _Mutex>
88class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
89#if !defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD)
90lock_guard
91#else
92lock_guard<_Mutex>
93#endif
94{
95public:
96    typedef _Mutex mutex_type;
97
98private:
99    mutex_type& __m_;
100public:
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
111private:
112    lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE;
113    lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE;
114};
115
116template <class _Mutex>
117class _LIBCPP_TYPE_VIS_ONLY unique_lock
118{
119public:
120    typedef _Mutex mutex_type;
121
122private:
123    mutex_type* __m_;
124    bool __owns_;
125
126public:
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
156private:
157    unique_lock(unique_lock const&); // = delete;
158    unique_lock& operator=(unique_lock const&); // = delete;
159
160public:
161#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
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_HAS_NO_RVALUE_REFERENCES
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
214template <class _Mutex>
215void
216unique_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
226template <class _Mutex>
227bool
228unique_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
238template <class _Mutex>
239template <class _Rep, class _Period>
240bool
241unique_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
251template <class _Mutex>
252template <class _Clock, class _Duration>
253bool
254unique_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
264template <class _Mutex>
265void
266unique_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
274template <class _Mutex>
275inline _LIBCPP_INLINE_VISIBILITY
276void
277swap(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
288class _LIBCPP_TYPE_VIS condition_variable
289{
290    __libcpp_condvar_t  __cv_;
291public:
292    _LIBCPP_INLINE_VISIBILITY
293#ifndef _LIBCPP_HAS_NO_CONSTEXPR
294    constexpr condition_variable() : __cv_(_LIBCPP_CONDVAR_INITIALIZER) {}
295#else
296    condition_variable() {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;}
297#endif
298    ~condition_variable();
299
300private:
301    condition_variable(const condition_variable&); // = delete;
302    condition_variable& operator=(const condition_variable&); // = delete;
303
304public:
305    void notify_one() _NOEXCEPT;
306    void notify_all() _NOEXCEPT;
307
308    void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
309    template <class _Predicate>
310        void wait(unique_lock<mutex>& __lk, _Predicate __pred);
311
312    template <class _Clock, class _Duration>
313        cv_status
314        wait_until(unique_lock<mutex>& __lk,
315                   const chrono::time_point<_Clock, _Duration>& __t);
316
317    template <class _Clock, class _Duration, class _Predicate>
318        bool
319        wait_until(unique_lock<mutex>& __lk,
320                   const chrono::time_point<_Clock, _Duration>& __t,
321                   _Predicate __pred);
322
323    template <class _Rep, class _Period>
324        cv_status
325        wait_for(unique_lock<mutex>& __lk,
326                 const chrono::duration<_Rep, _Period>& __d);
327
328    template <class _Rep, class _Period, class _Predicate>
329        bool
330        _LIBCPP_INLINE_VISIBILITY
331        wait_for(unique_lock<mutex>& __lk,
332                 const chrono::duration<_Rep, _Period>& __d,
333                 _Predicate __pred);
334
335    typedef __libcpp_condvar_t* native_handle_type;
336    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
337
338private:
339    void __do_timed_wait(unique_lock<mutex>& __lk,
340       chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
341};
342#endif // !_LIBCPP_HAS_NO_THREADS
343
344template <class _To, class _Rep, class _Period>
345inline _LIBCPP_INLINE_VISIBILITY
346typename enable_if
347<
348    chrono::__is_duration<_To>::value,
349    _To
350>::type
351__ceil(chrono::duration<_Rep, _Period> __d)
352{
353    using namespace chrono;
354    _To __r = duration_cast<_To>(__d);
355    if (__r < __d)
356        ++__r;
357    return __r;
358}
359
360#ifndef _LIBCPP_HAS_NO_THREADS
361template <class _Predicate>
362void
363condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
364{
365    while (!__pred())
366        wait(__lk);
367}
368
369template <class _Clock, class _Duration>
370cv_status
371condition_variable::wait_until(unique_lock<mutex>& __lk,
372                               const chrono::time_point<_Clock, _Duration>& __t)
373{
374    using namespace chrono;
375    wait_for(__lk, __t - _Clock::now());
376    return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
377}
378
379template <class _Clock, class _Duration, class _Predicate>
380bool
381condition_variable::wait_until(unique_lock<mutex>& __lk,
382                   const chrono::time_point<_Clock, _Duration>& __t,
383                   _Predicate __pred)
384{
385    while (!__pred())
386    {
387        if (wait_until(__lk, __t) == cv_status::timeout)
388            return __pred();
389    }
390    return true;
391}
392
393template <class _Rep, class _Period>
394cv_status
395condition_variable::wait_for(unique_lock<mutex>& __lk,
396                             const chrono::duration<_Rep, _Period>& __d)
397{
398    using namespace chrono;
399    if (__d <= __d.zero())
400        return cv_status::timeout;
401    typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
402    typedef time_point<system_clock, nanoseconds> __sys_tpi;
403    __sys_tpf _Max = __sys_tpi::max();
404    system_clock::time_point __s_now = system_clock::now();
405    steady_clock::time_point __c_now = steady_clock::now();
406    if (_Max - __d > __s_now)
407        __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
408    else
409        __do_timed_wait(__lk, __sys_tpi::max());
410    return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
411                                                 cv_status::timeout;
412}
413
414template <class _Rep, class _Period, class _Predicate>
415inline
416bool
417condition_variable::wait_for(unique_lock<mutex>& __lk,
418                             const chrono::duration<_Rep, _Period>& __d,
419                             _Predicate __pred)
420{
421    return wait_until(__lk, chrono::steady_clock::now() + __d,
422                      _VSTD::move(__pred));
423}
424
425#endif // !_LIBCPP_HAS_NO_THREADS
426
427_LIBCPP_END_NAMESPACE_STD
428
429#endif  // _LIBCPP___MUTEX_BASE
430