__mutex_base revision 249998
1227825Stheraven// -*- C++ -*-
2227825Stheraven//===----------------------------------------------------------------------===//
3227825Stheraven//
4227825Stheraven//                     The LLVM Compiler Infrastructure
5227825Stheraven//
6227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
7227825Stheraven// Source Licenses. See LICENSE.TXT for details.
8227825Stheraven//
9227825Stheraven//===----------------------------------------------------------------------===//
10227825Stheraven
11227825Stheraven#ifndef _LIBCPP___MUTEX_BASE
12227825Stheraven#define _LIBCPP___MUTEX_BASE
13227825Stheraven
14227825Stheraven#include <__config>
15227825Stheraven#include <chrono>
16227825Stheraven#include <system_error>
17227825Stheraven#include <pthread.h>
18227825Stheraven
19227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20227825Stheraven#pragma GCC system_header
21227825Stheraven#endif
22227825Stheraven
23227825Stheraven#ifdef _LIBCPP_SHARED_LOCK
24227825Stheraven
25227825Stheravennamespace ting {
26227825Stheraventemplate <class _Mutex> class shared_lock;
27227825Stheraventemplate <class _Mutex> class upgrade_lock;
28227825Stheraven}
29227825Stheraven
30227825Stheraven#endif  // _LIBCPP_SHARED_LOCK
31227825Stheraven
32227825Stheraven
33227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
34227825Stheraven
35249998Sdimclass _LIBCPP_TYPE_VIS mutex
36227825Stheraven{
37227825Stheraven    pthread_mutex_t __m_;
38227825Stheraven
39227825Stheravenpublic:
40227825Stheraven    _LIBCPP_INLINE_VISIBILITY
41241903Sdim#ifndef _LIBCPP_HAS_NO_CONSTEXPR
42241903Sdim     constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {}
43241903Sdim#else
44241903Sdim     mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
45241903Sdim#endif
46227825Stheraven     ~mutex();
47227825Stheraven
48227825Stheravenprivate:
49227825Stheraven    mutex(const mutex&);// = delete;
50227825Stheraven    mutex& operator=(const mutex&);// = delete;
51227825Stheraven
52227825Stheravenpublic:
53227825Stheraven    void lock();
54241903Sdim    bool try_lock() _NOEXCEPT;
55241903Sdim    void unlock() _NOEXCEPT;
56227825Stheraven
57227825Stheraven    typedef pthread_mutex_t* native_handle_type;
58227825Stheraven    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
59227825Stheraven};
60227825Stheraven
61249998Sdimstruct _LIBCPP_TYPE_VIS defer_lock_t {};
62249998Sdimstruct _LIBCPP_TYPE_VIS try_to_lock_t {};
63249998Sdimstruct _LIBCPP_TYPE_VIS adopt_lock_t {};
64227825Stheraven
65241903Sdim#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
66227825Stheraven
67241903Sdimextern const defer_lock_t  defer_lock;
68241903Sdimextern const try_to_lock_t try_to_lock;
69241903Sdimextern const adopt_lock_t  adopt_lock;
70227825Stheraven
71241903Sdim#else
72227825Stheraven
73241903Sdimconstexpr defer_lock_t  defer_lock  = defer_lock_t();
74241903Sdimconstexpr try_to_lock_t try_to_lock = try_to_lock_t();
75241903Sdimconstexpr adopt_lock_t  adopt_lock  = adopt_lock_t();
76241903Sdim
77241903Sdim#endif
78241903Sdim
79227825Stheraventemplate <class _Mutex>
80249998Sdimclass _LIBCPP_TYPE_VIS lock_guard
81227825Stheraven{
82227825Stheravenpublic:
83227825Stheraven    typedef _Mutex mutex_type;
84227825Stheraven
85227825Stheravenprivate:
86227825Stheraven    mutex_type& __m_;
87227825Stheravenpublic:
88227825Stheraven
89227825Stheraven    _LIBCPP_INLINE_VISIBILITY
90227825Stheraven    explicit lock_guard(mutex_type& __m)
91227825Stheraven        : __m_(__m) {__m_.lock();}
92227825Stheraven    _LIBCPP_INLINE_VISIBILITY
93227825Stheraven    lock_guard(mutex_type& __m, adopt_lock_t)
94227825Stheraven        : __m_(__m) {}
95227825Stheraven    _LIBCPP_INLINE_VISIBILITY
96227825Stheraven    ~lock_guard() {__m_.unlock();}
97227825Stheraven
98227825Stheravenprivate:
99227825Stheraven    lock_guard(lock_guard const&);// = delete;
100227825Stheraven    lock_guard& operator=(lock_guard const&);// = delete;
101227825Stheraven};
102227825Stheraven
103227825Stheraventemplate <class _Mutex>
104249998Sdimclass _LIBCPP_TYPE_VIS unique_lock
105227825Stheraven{
106227825Stheravenpublic:
107227825Stheraven    typedef _Mutex mutex_type;
108227825Stheraven
109227825Stheravenprivate:
110227825Stheraven    mutex_type* __m_;
111227825Stheraven    bool __owns_;
112227825Stheraven
113227825Stheravenpublic:
114227825Stheraven    _LIBCPP_INLINE_VISIBILITY
115241903Sdim    unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
116227825Stheraven    _LIBCPP_INLINE_VISIBILITY
117227825Stheraven    explicit unique_lock(mutex_type& __m)
118227825Stheraven        : __m_(&__m), __owns_(true) {__m_->lock();}
119227825Stheraven    _LIBCPP_INLINE_VISIBILITY
120241903Sdim    unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
121227825Stheraven        : __m_(&__m), __owns_(false) {}
122227825Stheraven    _LIBCPP_INLINE_VISIBILITY
123227825Stheraven    unique_lock(mutex_type& __m, try_to_lock_t)
124227825Stheraven        : __m_(&__m), __owns_(__m.try_lock()) {}
125227825Stheraven    _LIBCPP_INLINE_VISIBILITY
126227825Stheraven    unique_lock(mutex_type& __m, adopt_lock_t)
127227825Stheraven        : __m_(&__m), __owns_(true) {}
128227825Stheraven    template <class _Clock, class _Duration>
129227825Stheraven    _LIBCPP_INLINE_VISIBILITY
130227825Stheraven        unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
131227825Stheraven            : __m_(&__m), __owns_(__m.try_lock_until(__t)) {}
132227825Stheraven    template <class _Rep, class _Period>
133227825Stheraven    _LIBCPP_INLINE_VISIBILITY
134227825Stheraven        unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
135227825Stheraven            : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
136227825Stheraven    _LIBCPP_INLINE_VISIBILITY
137227825Stheraven    ~unique_lock()
138227825Stheraven    {
139227825Stheraven        if (__owns_)
140227825Stheraven            __m_->unlock();
141227825Stheraven    }
142227825Stheraven
143227825Stheravenprivate:
144227825Stheraven    unique_lock(unique_lock const&); // = delete;
145227825Stheraven    unique_lock& operator=(unique_lock const&); // = delete;
146227825Stheraven
147227825Stheravenpublic:
148227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
149227825Stheraven    _LIBCPP_INLINE_VISIBILITY
150241903Sdim    unique_lock(unique_lock&& __u) _NOEXCEPT
151227825Stheraven        : __m_(__u.__m_), __owns_(__u.__owns_)
152227825Stheraven        {__u.__m_ = nullptr; __u.__owns_ = false;}
153227825Stheraven    _LIBCPP_INLINE_VISIBILITY
154241903Sdim    unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
155227825Stheraven        {
156227825Stheraven            if (__owns_)
157227825Stheraven                __m_->unlock();
158227825Stheraven            __m_ = __u.__m_;
159227825Stheraven            __owns_ = __u.__owns_;
160227825Stheraven            __u.__m_ = nullptr;
161227825Stheraven            __u.__owns_ = false;
162227825Stheraven            return *this;
163227825Stheraven        }
164227825Stheraven
165227825Stheraven#ifdef _LIBCPP_SHARED_LOCK
166227825Stheraven
167227825Stheraven    unique_lock(ting::shared_lock<mutex_type>&&, try_to_lock_t);
168227825Stheraven    template <class _Clock, class _Duration>
169227825Stheraven        unique_lock(ting::shared_lock<mutex_type>&&,
170227825Stheraven                    const chrono::time_point<_Clock, _Duration>&);
171227825Stheraven    template <class _Rep, class _Period>
172227825Stheraven        unique_lock(ting::shared_lock<mutex_type>&&,
173227825Stheraven                    const chrono::duration<_Rep, _Period>&);
174227825Stheraven
175227825Stheraven    explicit unique_lock(ting::upgrade_lock<mutex_type>&&);
176227825Stheraven    unique_lock(ting::upgrade_lock<mutex_type>&&, try_to_lock_t);
177227825Stheraven    template <class _Clock, class _Duration>
178227825Stheraven        unique_lock(ting::upgrade_lock<mutex_type>&&,
179227825Stheraven                    const chrono::time_point<_Clock, _Duration>&);
180227825Stheraven    template <class _Rep, class _Period>
181227825Stheraven        unique_lock(ting::upgrade_lock<mutex_type>&&,
182227825Stheraven                    const chrono::duration<_Rep, _Period>&);
183227825Stheraven
184227825Stheraven#endif  // _LIBCPP_SHARED_LOCK
185227825Stheraven
186227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
187227825Stheraven
188227825Stheraven    void lock();
189227825Stheraven    bool try_lock();
190227825Stheraven
191227825Stheraven    template <class _Rep, class _Period>
192227825Stheraven        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
193227825Stheraven    template <class _Clock, class _Duration>
194227825Stheraven        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
195227825Stheraven
196227825Stheraven    void unlock();
197227825Stheraven
198227825Stheraven    _LIBCPP_INLINE_VISIBILITY
199241903Sdim    void swap(unique_lock& __u) _NOEXCEPT
200227825Stheraven    {
201227825Stheraven        _VSTD::swap(__m_, __u.__m_);
202227825Stheraven        _VSTD::swap(__owns_, __u.__owns_);
203227825Stheraven    }
204227825Stheraven    _LIBCPP_INLINE_VISIBILITY
205241903Sdim    mutex_type* release() _NOEXCEPT
206227825Stheraven    {
207227825Stheraven        mutex_type* __m = __m_;
208227825Stheraven        __m_ = nullptr;
209227825Stheraven        __owns_ = false;
210227825Stheraven        return __m;
211227825Stheraven    }
212227825Stheraven
213227825Stheraven    _LIBCPP_INLINE_VISIBILITY
214241903Sdim    bool owns_lock() const _NOEXCEPT {return __owns_;}
215227825Stheraven    _LIBCPP_INLINE_VISIBILITY
216232950Stheraven    _LIBCPP_EXPLICIT
217241903Sdim        operator bool () const _NOEXCEPT {return __owns_;}
218227825Stheraven    _LIBCPP_INLINE_VISIBILITY
219241903Sdim    mutex_type* mutex() const _NOEXCEPT {return __m_;}
220227825Stheraven};
221227825Stheraven
222227825Stheraventemplate <class _Mutex>
223227825Stheravenvoid
224227825Stheravenunique_lock<_Mutex>::lock()
225227825Stheraven{
226227825Stheraven    if (__m_ == nullptr)
227227825Stheraven        __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
228227825Stheraven    if (__owns_)
229227825Stheraven        __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
230227825Stheraven    __m_->lock();
231227825Stheraven    __owns_ = true;
232227825Stheraven}
233227825Stheraven
234227825Stheraventemplate <class _Mutex>
235227825Stheravenbool
236227825Stheravenunique_lock<_Mutex>::try_lock()
237227825Stheraven{
238227825Stheraven    if (__m_ == nullptr)
239227825Stheraven        __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
240227825Stheraven    if (__owns_)
241227825Stheraven        __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
242227825Stheraven    __owns_ = __m_->try_lock();
243227825Stheraven    return __owns_;
244227825Stheraven}
245227825Stheraven
246227825Stheraventemplate <class _Mutex>
247227825Stheraventemplate <class _Rep, class _Period>
248227825Stheravenbool
249227825Stheravenunique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
250227825Stheraven{
251227825Stheraven    if (__m_ == nullptr)
252227825Stheraven        __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
253227825Stheraven    if (__owns_)
254227825Stheraven        __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
255227825Stheraven    __owns_ = __m_->try_lock_for(__d);
256227825Stheraven    return __owns_;
257227825Stheraven}
258227825Stheraven
259227825Stheraventemplate <class _Mutex>
260227825Stheraventemplate <class _Clock, class _Duration>
261227825Stheravenbool
262227825Stheravenunique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
263227825Stheraven{
264227825Stheraven    if (__m_ == nullptr)
265227825Stheraven        __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
266227825Stheraven    if (__owns_)
267227825Stheraven        __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
268227825Stheraven    __owns_ = __m_->try_lock_until(__t);
269227825Stheraven    return __owns_;
270227825Stheraven}
271227825Stheraven
272227825Stheraventemplate <class _Mutex>
273227825Stheravenvoid
274227825Stheravenunique_lock<_Mutex>::unlock()
275227825Stheraven{
276227825Stheraven    if (!__owns_)
277227825Stheraven        __throw_system_error(EPERM, "unique_lock::unlock: not locked");
278227825Stheraven    __m_->unlock();
279227825Stheraven    __owns_ = false;
280227825Stheraven}
281227825Stheraven
282227825Stheraventemplate <class _Mutex>
283227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
284227825Stheravenvoid
285241903Sdimswap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
286241903Sdim    {__x.swap(__y);}
287227825Stheraven
288249998Sdimstruct _LIBCPP_TYPE_VIS cv_status
289227825Stheraven{
290242945Stheraven    enum __lx {
291227825Stheraven        no_timeout,
292227825Stheraven        timeout
293227825Stheraven    };
294227825Stheraven
295242945Stheraven    __lx __v_;
296227825Stheraven
297242945Stheraven    _LIBCPP_INLINE_VISIBILITY cv_status(__lx __v) : __v_(__v) {}
298227825Stheraven    _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;}
299227825Stheraven
300227825Stheraven};
301227825Stheraven
302249998Sdimclass _LIBCPP_TYPE_VIS condition_variable
303227825Stheraven{
304227825Stheraven    pthread_cond_t __cv_;
305227825Stheravenpublic:
306227825Stheraven    _LIBCPP_INLINE_VISIBILITY
307241903Sdim#ifndef _LIBCPP_HAS_NO_CONSTEXPR
308241903Sdim    constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {}
309241903Sdim#else
310227825Stheraven    condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
311241903Sdim#endif
312227825Stheraven    ~condition_variable();
313227825Stheraven
314227825Stheravenprivate:
315227825Stheraven    condition_variable(const condition_variable&); // = delete;
316227825Stheraven    condition_variable& operator=(const condition_variable&); // = delete;
317227825Stheraven
318227825Stheravenpublic:
319241903Sdim    void notify_one() _NOEXCEPT;
320241903Sdim    void notify_all() _NOEXCEPT;
321227825Stheraven
322227825Stheraven    void wait(unique_lock<mutex>& __lk);
323227825Stheraven    template <class _Predicate>
324227825Stheraven        void wait(unique_lock<mutex>& __lk, _Predicate __pred);
325227825Stheraven
326227825Stheraven    template <class _Clock, class _Duration>
327227825Stheraven        cv_status
328227825Stheraven        wait_until(unique_lock<mutex>& __lk,
329227825Stheraven                   const chrono::time_point<_Clock, _Duration>& __t);
330227825Stheraven
331227825Stheraven    template <class _Clock, class _Duration, class _Predicate>
332227825Stheraven        bool
333227825Stheraven        wait_until(unique_lock<mutex>& __lk,
334227825Stheraven                   const chrono::time_point<_Clock, _Duration>& __t,
335227825Stheraven                   _Predicate __pred);
336227825Stheraven
337227825Stheraven    template <class _Rep, class _Period>
338227825Stheraven        cv_status
339227825Stheraven        wait_for(unique_lock<mutex>& __lk,
340227825Stheraven                 const chrono::duration<_Rep, _Period>& __d);
341227825Stheraven
342227825Stheraven    template <class _Rep, class _Period, class _Predicate>
343227825Stheraven        bool
344227825Stheraven        wait_for(unique_lock<mutex>& __lk,
345227825Stheraven                 const chrono::duration<_Rep, _Period>& __d,
346227825Stheraven                 _Predicate __pred);
347227825Stheraven
348227825Stheraven    typedef pthread_cond_t* native_handle_type;
349227825Stheraven    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
350227825Stheraven
351227825Stheravenprivate:
352227825Stheraven    void __do_timed_wait(unique_lock<mutex>& __lk,
353227825Stheraven                 chrono::time_point<chrono::system_clock, chrono::nanoseconds>);
354227825Stheraven};
355227825Stheraven
356227825Stheraventemplate <class _To, class _Rep, class _Period>
357227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
358227825Stheraventypename enable_if
359227825Stheraven<
360227825Stheraven    chrono::__is_duration<_To>::value,
361227825Stheraven    _To
362227825Stheraven>::type
363227825Stheraven__ceil(chrono::duration<_Rep, _Period> __d)
364227825Stheraven{
365227825Stheraven    using namespace chrono;
366227825Stheraven    _To __r = duration_cast<_To>(__d);
367227825Stheraven    if (__r < __d)
368227825Stheraven        ++__r;
369227825Stheraven    return __r;
370227825Stheraven}
371227825Stheraven
372227825Stheraventemplate <class _Predicate>
373227825Stheravenvoid
374227825Stheravencondition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
375227825Stheraven{
376227825Stheraven    while (!__pred())
377227825Stheraven        wait(__lk);
378227825Stheraven}
379227825Stheraven
380227825Stheraventemplate <class _Clock, class _Duration>
381227825Stheravencv_status
382227825Stheravencondition_variable::wait_until(unique_lock<mutex>& __lk,
383227825Stheraven                               const chrono::time_point<_Clock, _Duration>& __t)
384227825Stheraven{
385227825Stheraven    using namespace chrono;
386241903Sdim    wait_for(__lk, __t - _Clock::now());
387227825Stheraven    return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
388227825Stheraven}
389227825Stheraven
390227825Stheraventemplate <class _Clock, class _Duration, class _Predicate>
391227825Stheravenbool
392227825Stheravencondition_variable::wait_until(unique_lock<mutex>& __lk,
393227825Stheraven                   const chrono::time_point<_Clock, _Duration>& __t,
394227825Stheraven                   _Predicate __pred)
395227825Stheraven{
396227825Stheraven    while (!__pred())
397227825Stheraven    {
398227825Stheraven        if (wait_until(__lk, __t) == cv_status::timeout)
399227825Stheraven            return __pred();
400227825Stheraven    }
401227825Stheraven    return true;
402227825Stheraven}
403227825Stheraven
404227825Stheraventemplate <class _Rep, class _Period>
405227825Stheravencv_status
406227825Stheravencondition_variable::wait_for(unique_lock<mutex>& __lk,
407227825Stheraven                             const chrono::duration<_Rep, _Period>& __d)
408227825Stheraven{
409227825Stheraven    using namespace chrono;
410241903Sdim    if (__d <= __d.zero())
411241903Sdim        return cv_status::timeout;
412241903Sdim    typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
413241903Sdim    typedef time_point<system_clock, nanoseconds> __sys_tpi;
414241903Sdim    __sys_tpf _Max = __sys_tpi::max();
415227825Stheraven    system_clock::time_point __s_now = system_clock::now();
416227825Stheraven    steady_clock::time_point __c_now = steady_clock::now();
417241903Sdim    if (_Max - __d > __s_now)
418241903Sdim        __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
419241903Sdim    else
420241903Sdim        __do_timed_wait(__lk, __sys_tpi::max());
421227825Stheraven    return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
422227825Stheraven                                                 cv_status::timeout;
423227825Stheraven}
424227825Stheraven
425227825Stheraventemplate <class _Rep, class _Period, class _Predicate>
426227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
427227825Stheravenbool
428227825Stheravencondition_variable::wait_for(unique_lock<mutex>& __lk,
429227825Stheraven                             const chrono::duration<_Rep, _Period>& __d,
430227825Stheraven                             _Predicate __pred)
431227825Stheraven{
432227825Stheraven    return wait_until(__lk, chrono::steady_clock::now() + __d,
433227825Stheraven                      _VSTD::move(__pred));
434227825Stheraven}
435227825Stheraven
436227825Stheraven_LIBCPP_END_NAMESPACE_STD
437227825Stheraven
438227825Stheraven#endif  // _LIBCPP___MUTEX_BASE
439