__mutex_base revision 261272
1251881Speter// -*- C++ -*-
2251881Speter//===----------------------------------------------------------------------===//
3251881Speter//
4251881Speter//                     The LLVM Compiler Infrastructure
5251881Speter//
6251881Speter// This file is dual licensed under the MIT and the University of Illinois Open
7251881Speter// Source Licenses. See LICENSE.TXT for details.
8251881Speter//
9251881Speter//===----------------------------------------------------------------------===//
10251881Speter
11251881Speter#ifndef _LIBCPP___MUTEX_BASE
12251881Speter#define _LIBCPP___MUTEX_BASE
13251881Speter
14251881Speter#include <__config>
15251881Speter#include <chrono>
16251881Speter#include <system_error>
17251881Speter#include <pthread.h>
18251881Speter
19251881Speter#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20251881Speter#pragma GCC system_header
21251881Speter#endif
22251881Speter
23251881Speter_LIBCPP_BEGIN_NAMESPACE_STD
24251881Speter
25251881Speterclass _LIBCPP_TYPE_VIS mutex
26251881Speter{
27251881Speter    pthread_mutex_t __m_;
28251881Speter
29251881Speterpublic:
30251881Speter    _LIBCPP_INLINE_VISIBILITY
31251881Speter#ifndef _LIBCPP_HAS_NO_CONSTEXPR
32251881Speter     constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {}
33251881Speter#else
34251881Speter     mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
35251881Speter#endif
36251881Speter     ~mutex();
37251881Speter
38251881Speterprivate:
39251881Speter    mutex(const mutex&);// = delete;
40251881Speter    mutex& operator=(const mutex&);// = delete;
41251881Speter
42251881Speterpublic:
43251881Speter    void lock();
44251881Speter    bool try_lock() _NOEXCEPT;
45251881Speter    void unlock() _NOEXCEPT;
46251881Speter
47251881Speter    typedef pthread_mutex_t* native_handle_type;
48251881Speter    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
49251881Speter};
50251881Speter
51251881Speterstruct _LIBCPP_TYPE_VIS defer_lock_t {};
52251881Speterstruct _LIBCPP_TYPE_VIS try_to_lock_t {};
53251881Speterstruct _LIBCPP_TYPE_VIS adopt_lock_t {};
54251881Speter
55251881Speter#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
56251881Speter
57251881Speterextern const defer_lock_t  defer_lock;
58251881Speterextern const try_to_lock_t try_to_lock;
59251881Speterextern const adopt_lock_t  adopt_lock;
60251881Speter
61251881Speter#else
62251881Speter
63251881Speterconstexpr defer_lock_t  defer_lock  = defer_lock_t();
64251881Speterconstexpr try_to_lock_t try_to_lock = try_to_lock_t();
65251881Speterconstexpr adopt_lock_t  adopt_lock  = adopt_lock_t();
66251881Speter
67251881Speter#endif
68251881Speter
69251881Spetertemplate <class _Mutex>
70251881Speterclass _LIBCPP_TYPE_VIS_ONLY lock_guard
71251881Speter{
72251881Speterpublic:
73251881Speter    typedef _Mutex mutex_type;
74251881Speter
75251881Speterprivate:
76251881Speter    mutex_type& __m_;
77251881Speterpublic:
78251881Speter
79251881Speter    _LIBCPP_INLINE_VISIBILITY
80251881Speter    explicit lock_guard(mutex_type& __m)
81251881Speter        : __m_(__m) {__m_.lock();}
82251881Speter    _LIBCPP_INLINE_VISIBILITY
83251881Speter    lock_guard(mutex_type& __m, adopt_lock_t)
84251881Speter        : __m_(__m) {}
85251881Speter    _LIBCPP_INLINE_VISIBILITY
86251881Speter    ~lock_guard() {__m_.unlock();}
87251881Speter
88251881Speterprivate:
89251881Speter    lock_guard(lock_guard const&);// = delete;
90251881Speter    lock_guard& operator=(lock_guard const&);// = delete;
91251881Speter};
92251881Speter
93251881Spetertemplate <class _Mutex>
94251881Speterclass _LIBCPP_TYPE_VIS_ONLY unique_lock
95251881Speter{
96251881Speterpublic:
97251881Speter    typedef _Mutex mutex_type;
98251881Speter
99251881Speterprivate:
100251881Speter    mutex_type* __m_;
101251881Speter    bool __owns_;
102251881Speter
103251881Speterpublic:
104251881Speter    _LIBCPP_INLINE_VISIBILITY
105251881Speter    unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
106251881Speter    _LIBCPP_INLINE_VISIBILITY
107251881Speter    explicit unique_lock(mutex_type& __m)
108251881Speter        : __m_(&__m), __owns_(true) {__m_->lock();}
109251881Speter    _LIBCPP_INLINE_VISIBILITY
110251881Speter    unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
111251881Speter        : __m_(&__m), __owns_(false) {}
112251881Speter    _LIBCPP_INLINE_VISIBILITY
113251881Speter    unique_lock(mutex_type& __m, try_to_lock_t)
114251881Speter        : __m_(&__m), __owns_(__m.try_lock()) {}
115251881Speter    _LIBCPP_INLINE_VISIBILITY
116251881Speter    unique_lock(mutex_type& __m, adopt_lock_t)
117251881Speter        : __m_(&__m), __owns_(true) {}
118251881Speter    template <class _Clock, class _Duration>
119251881Speter    _LIBCPP_INLINE_VISIBILITY
120251881Speter        unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
121251881Speter            : __m_(&__m), __owns_(__m.try_lock_until(__t)) {}
122251881Speter    template <class _Rep, class _Period>
123251881Speter    _LIBCPP_INLINE_VISIBILITY
124251881Speter        unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
125251881Speter            : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
126251881Speter    _LIBCPP_INLINE_VISIBILITY
127251881Speter    ~unique_lock()
128251881Speter    {
129251881Speter        if (__owns_)
130251881Speter            __m_->unlock();
131251881Speter    }
132251881Speter
133251881Speterprivate:
134251881Speter    unique_lock(unique_lock const&); // = delete;
135251881Speter    unique_lock& operator=(unique_lock const&); // = delete;
136251881Speter
137251881Speterpublic:
138251881Speter#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
139251881Speter    _LIBCPP_INLINE_VISIBILITY
140251881Speter    unique_lock(unique_lock&& __u) _NOEXCEPT
141251881Speter        : __m_(__u.__m_), __owns_(__u.__owns_)
142251881Speter        {__u.__m_ = nullptr; __u.__owns_ = false;}
143251881Speter    _LIBCPP_INLINE_VISIBILITY
144251881Speter    unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
145251881Speter        {
146251881Speter            if (__owns_)
147251881Speter                __m_->unlock();
148251881Speter            __m_ = __u.__m_;
149251881Speter            __owns_ = __u.__owns_;
150251881Speter            __u.__m_ = nullptr;
151251881Speter            __u.__owns_ = false;
152251881Speter            return *this;
153251881Speter        }
154251881Speter
155251881Speter#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
156251881Speter
157251881Speter    void lock();
158251881Speter    bool try_lock();
159251881Speter
160251881Speter    template <class _Rep, class _Period>
161251881Speter        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
162251881Speter    template <class _Clock, class _Duration>
163251881Speter        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
164251881Speter
165251881Speter    void unlock();
166251881Speter
167251881Speter    _LIBCPP_INLINE_VISIBILITY
168251881Speter    void swap(unique_lock& __u) _NOEXCEPT
169251881Speter    {
170251881Speter        _VSTD::swap(__m_, __u.__m_);
171251881Speter        _VSTD::swap(__owns_, __u.__owns_);
172251881Speter    }
173251881Speter    _LIBCPP_INLINE_VISIBILITY
174251881Speter    mutex_type* release() _NOEXCEPT
175251881Speter    {
176251881Speter        mutex_type* __m = __m_;
177251881Speter        __m_ = nullptr;
178251881Speter        __owns_ = false;
179251881Speter        return __m;
180251881Speter    }
181251881Speter
182251881Speter    _LIBCPP_INLINE_VISIBILITY
183251881Speter    bool owns_lock() const _NOEXCEPT {return __owns_;}
184251881Speter    _LIBCPP_INLINE_VISIBILITY
185251881Speter    _LIBCPP_EXPLICIT
186251881Speter        operator bool () const _NOEXCEPT {return __owns_;}
187251881Speter    _LIBCPP_INLINE_VISIBILITY
188251881Speter    mutex_type* mutex() const _NOEXCEPT {return __m_;}
189251881Speter};
190251881Speter
191251881Spetertemplate <class _Mutex>
192251881Spetervoid
193251881Speterunique_lock<_Mutex>::lock()
194251881Speter{
195251881Speter    if (__m_ == nullptr)
196251881Speter        __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
197251881Speter    if (__owns_)
198251881Speter        __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
199251881Speter    __m_->lock();
200251881Speter    __owns_ = true;
201251881Speter}
202251881Speter
203251881Spetertemplate <class _Mutex>
204251881Speterbool
205251881Speterunique_lock<_Mutex>::try_lock()
206251881Speter{
207251881Speter    if (__m_ == nullptr)
208251881Speter        __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
209251881Speter    if (__owns_)
210251881Speter        __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
211251881Speter    __owns_ = __m_->try_lock();
212251881Speter    return __owns_;
213251881Speter}
214251881Speter
215251881Spetertemplate <class _Mutex>
216251881Spetertemplate <class _Rep, class _Period>
217251881Speterbool
218251881Speterunique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
219251881Speter{
220251881Speter    if (__m_ == nullptr)
221251881Speter        __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
222251881Speter    if (__owns_)
223251881Speter        __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
224251881Speter    __owns_ = __m_->try_lock_for(__d);
225251881Speter    return __owns_;
226251881Speter}
227251881Speter
228251881Spetertemplate <class _Mutex>
229251881Spetertemplate <class _Clock, class _Duration>
230251881Speterbool
231251881Speterunique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
232251881Speter{
233251881Speter    if (__m_ == nullptr)
234251881Speter        __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
235251881Speter    if (__owns_)
236251881Speter        __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
237251881Speter    __owns_ = __m_->try_lock_until(__t);
238251881Speter    return __owns_;
239251881Speter}
240251881Speter
241251881Spetertemplate <class _Mutex>
242251881Spetervoid
243251881Speterunique_lock<_Mutex>::unlock()
244251881Speter{
245251881Speter    if (!__owns_)
246251881Speter        __throw_system_error(EPERM, "unique_lock::unlock: not locked");
247251881Speter    __m_->unlock();
248251881Speter    __owns_ = false;
249251881Speter}
250251881Speter
251251881Spetertemplate <class _Mutex>
252251881Speterinline _LIBCPP_INLINE_VISIBILITY
253251881Spetervoid
254251881Speterswap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
255251881Speter    {__x.swap(__y);}
256251881Speter
257251881Speterstruct _LIBCPP_TYPE_VIS cv_status
258251881Speter{
259251881Speter    enum __lx {
260251881Speter        no_timeout,
261251881Speter        timeout
262251881Speter    };
263251881Speter
264251881Speter    __lx __v_;
265251881Speter
266251881Speter    _LIBCPP_INLINE_VISIBILITY cv_status(__lx __v) : __v_(__v) {}
267251881Speter    _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;}
268251881Speter
269251881Speter};
270251881Speter
271251881Speterclass _LIBCPP_TYPE_VIS condition_variable
272251881Speter{
273251881Speter    pthread_cond_t __cv_;
274251881Speterpublic:
275251881Speter    _LIBCPP_INLINE_VISIBILITY
276251881Speter#ifndef _LIBCPP_HAS_NO_CONSTEXPR
277251881Speter    constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {}
278251881Speter#else
279251881Speter    condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
280251881Speter#endif
281251881Speter    ~condition_variable();
282251881Speter
283251881Speterprivate:
284251881Speter    condition_variable(const condition_variable&); // = delete;
285251881Speter    condition_variable& operator=(const condition_variable&); // = delete;
286251881Speter
287251881Speterpublic:
288251881Speter    void notify_one() _NOEXCEPT;
289251881Speter    void notify_all() _NOEXCEPT;
290251881Speter
291251881Speter    void wait(unique_lock<mutex>& __lk);
292251881Speter    template <class _Predicate>
293251881Speter        void wait(unique_lock<mutex>& __lk, _Predicate __pred);
294251881Speter
295251881Speter    template <class _Clock, class _Duration>
296251881Speter        cv_status
297251881Speter        wait_until(unique_lock<mutex>& __lk,
298251881Speter                   const chrono::time_point<_Clock, _Duration>& __t);
299251881Speter
300251881Speter    template <class _Clock, class _Duration, class _Predicate>
301251881Speter        bool
302251881Speter        wait_until(unique_lock<mutex>& __lk,
303251881Speter                   const chrono::time_point<_Clock, _Duration>& __t,
304251881Speter                   _Predicate __pred);
305251881Speter
306251881Speter    template <class _Rep, class _Period>
307251881Speter        cv_status
308251881Speter        wait_for(unique_lock<mutex>& __lk,
309251881Speter                 const chrono::duration<_Rep, _Period>& __d);
310251881Speter
311251881Speter    template <class _Rep, class _Period, class _Predicate>
312251881Speter        bool
313251881Speter        wait_for(unique_lock<mutex>& __lk,
314251881Speter                 const chrono::duration<_Rep, _Period>& __d,
315251881Speter                 _Predicate __pred);
316251881Speter
317251881Speter    typedef pthread_cond_t* native_handle_type;
318251881Speter    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
319251881Speter
320251881Speterprivate:
321251881Speter    void __do_timed_wait(unique_lock<mutex>& __lk,
322251881Speter                 chrono::time_point<chrono::system_clock, chrono::nanoseconds>);
323251881Speter};
324251881Speter
325251881Spetertemplate <class _To, class _Rep, class _Period>
326251881Speterinline _LIBCPP_INLINE_VISIBILITY
327251881Spetertypename enable_if
328251881Speter<
329251881Speter    chrono::__is_duration<_To>::value,
330251881Speter    _To
331251881Speter>::type
332251881Speter__ceil(chrono::duration<_Rep, _Period> __d)
333251881Speter{
334251881Speter    using namespace chrono;
335251881Speter    _To __r = duration_cast<_To>(__d);
336251881Speter    if (__r < __d)
337251881Speter        ++__r;
338251881Speter    return __r;
339251881Speter}
340251881Speter
341251881Spetertemplate <class _Predicate>
342251881Spetervoid
343251881Spetercondition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
344251881Speter{
345251881Speter    while (!__pred())
346251881Speter        wait(__lk);
347251881Speter}
348251881Speter
349251881Spetertemplate <class _Clock, class _Duration>
350251881Spetercv_status
351251881Spetercondition_variable::wait_until(unique_lock<mutex>& __lk,
352251881Speter                               const chrono::time_point<_Clock, _Duration>& __t)
353251881Speter{
354251881Speter    using namespace chrono;
355251881Speter    wait_for(__lk, __t - _Clock::now());
356251881Speter    return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
357251881Speter}
358251881Speter
359251881Spetertemplate <class _Clock, class _Duration, class _Predicate>
360251881Speterbool
361251881Spetercondition_variable::wait_until(unique_lock<mutex>& __lk,
362251881Speter                   const chrono::time_point<_Clock, _Duration>& __t,
363251881Speter                   _Predicate __pred)
364251881Speter{
365251881Speter    while (!__pred())
366251881Speter    {
367251881Speter        if (wait_until(__lk, __t) == cv_status::timeout)
368251881Speter            return __pred();
369251881Speter    }
370251881Speter    return true;
371251881Speter}
372251881Speter
373251881Spetertemplate <class _Rep, class _Period>
374251881Spetercv_status
375251881Spetercondition_variable::wait_for(unique_lock<mutex>& __lk,
376251881Speter                             const chrono::duration<_Rep, _Period>& __d)
377251881Speter{
378251881Speter    using namespace chrono;
379251881Speter    if (__d <= __d.zero())
380251881Speter        return cv_status::timeout;
381251881Speter    typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
382251881Speter    typedef time_point<system_clock, nanoseconds> __sys_tpi;
383251881Speter    __sys_tpf _Max = __sys_tpi::max();
384251881Speter    system_clock::time_point __s_now = system_clock::now();
385251881Speter    steady_clock::time_point __c_now = steady_clock::now();
386251881Speter    if (_Max - __d > __s_now)
387251881Speter        __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
388251881Speter    else
389251881Speter        __do_timed_wait(__lk, __sys_tpi::max());
390251881Speter    return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
391251881Speter                                                 cv_status::timeout;
392251881Speter}
393251881Speter
394251881Spetertemplate <class _Rep, class _Period, class _Predicate>
395251881Speterinline _LIBCPP_INLINE_VISIBILITY
396251881Speterbool
397251881Spetercondition_variable::wait_for(unique_lock<mutex>& __lk,
398251881Speter                             const chrono::duration<_Rep, _Period>& __d,
399251881Speter                             _Predicate __pred)
400251881Speter{
401251881Speter    return wait_until(__lk, chrono::steady_clock::now() + __d,
402251881Speter                      _VSTD::move(__pred));
403251881Speter}
404251881Speter
405251881Speter_LIBCPP_END_NAMESPACE_STD
406251881Speter
407251881Speter#endif  // _LIBCPP___MUTEX_BASE
408251881Speter