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