xref: /minix3/external/bsd/libc++/dist/libcxx/include/shared_mutex (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
14684ddb6SLionel Sambuc// -*- C++ -*-
24684ddb6SLionel Sambuc//===------------------------ shared_mutex --------------------------------===//
34684ddb6SLionel Sambuc//
44684ddb6SLionel Sambuc//                     The LLVM Compiler Infrastructure
54684ddb6SLionel Sambuc//
64684ddb6SLionel Sambuc// This file is dual licensed under the MIT and the University of Illinois Open
74684ddb6SLionel Sambuc// Source Licenses. See LICENSE.TXT for details.
84684ddb6SLionel Sambuc//
94684ddb6SLionel Sambuc//===----------------------------------------------------------------------===//
104684ddb6SLionel Sambuc
114684ddb6SLionel Sambuc#ifndef _LIBCPP_SHARED_MUTEX
124684ddb6SLionel Sambuc#define _LIBCPP_SHARED_MUTEX
134684ddb6SLionel Sambuc
144684ddb6SLionel Sambuc/*
154684ddb6SLionel Sambuc    shared_mutex synopsis
164684ddb6SLionel Sambuc
174684ddb6SLionel Sambuc// C++1y
184684ddb6SLionel Sambuc
194684ddb6SLionel Sambucnamespace std
204684ddb6SLionel Sambuc{
214684ddb6SLionel Sambuc
22*0a6a1f1dSLionel Sambucclass shared_mutex      // C++17
234684ddb6SLionel Sambuc{
244684ddb6SLionel Sambucpublic:
254684ddb6SLionel Sambuc    shared_mutex();
264684ddb6SLionel Sambuc    ~shared_mutex();
274684ddb6SLionel Sambuc
284684ddb6SLionel Sambuc    shared_mutex(const shared_mutex&) = delete;
294684ddb6SLionel Sambuc    shared_mutex& operator=(const shared_mutex&) = delete;
304684ddb6SLionel Sambuc
314684ddb6SLionel Sambuc    // Exclusive ownership
324684ddb6SLionel Sambuc    void lock(); // blocking
334684ddb6SLionel Sambuc    bool try_lock();
34*0a6a1f1dSLionel Sambuc    void unlock();
35*0a6a1f1dSLionel Sambuc
36*0a6a1f1dSLionel Sambuc    // Shared ownership
37*0a6a1f1dSLionel Sambuc    void lock_shared(); // blocking
38*0a6a1f1dSLionel Sambuc    bool try_lock_shared();
39*0a6a1f1dSLionel Sambuc    void unlock_shared();
40*0a6a1f1dSLionel Sambuc
41*0a6a1f1dSLionel Sambuc    typedef implementation-defined native_handle_type; // See 30.2.3
42*0a6a1f1dSLionel Sambuc    native_handle_type native_handle(); // See 30.2.3
43*0a6a1f1dSLionel Sambuc};
44*0a6a1f1dSLionel Sambuc
45*0a6a1f1dSLionel Sambucclass shared_timed_mutex
46*0a6a1f1dSLionel Sambuc{
47*0a6a1f1dSLionel Sambucpublic:
48*0a6a1f1dSLionel Sambuc    shared_timed_mutex();
49*0a6a1f1dSLionel Sambuc    ~shared_timed_mutex();
50*0a6a1f1dSLionel Sambuc
51*0a6a1f1dSLionel Sambuc    shared_timed_mutex(const shared_timed_mutex&) = delete;
52*0a6a1f1dSLionel Sambuc    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
53*0a6a1f1dSLionel Sambuc
54*0a6a1f1dSLionel Sambuc    // Exclusive ownership
55*0a6a1f1dSLionel Sambuc    void lock(); // blocking
56*0a6a1f1dSLionel Sambuc    bool try_lock();
574684ddb6SLionel Sambuc    template <class Rep, class Period>
584684ddb6SLionel Sambuc        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
594684ddb6SLionel Sambuc    template <class Clock, class Duration>
604684ddb6SLionel Sambuc        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
614684ddb6SLionel Sambuc    void unlock();
624684ddb6SLionel Sambuc
634684ddb6SLionel Sambuc    // Shared ownership
644684ddb6SLionel Sambuc    void lock_shared(); // blocking
654684ddb6SLionel Sambuc    bool try_lock_shared();
664684ddb6SLionel Sambuc    template <class Rep, class Period>
674684ddb6SLionel Sambuc        bool
684684ddb6SLionel Sambuc        try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
694684ddb6SLionel Sambuc    template <class Clock, class Duration>
704684ddb6SLionel Sambuc        bool
714684ddb6SLionel Sambuc        try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
724684ddb6SLionel Sambuc    void unlock_shared();
734684ddb6SLionel Sambuc};
744684ddb6SLionel Sambuc
754684ddb6SLionel Sambuctemplate <class Mutex>
764684ddb6SLionel Sambucclass shared_lock
774684ddb6SLionel Sambuc{
784684ddb6SLionel Sambucpublic:
794684ddb6SLionel Sambuc    typedef Mutex mutex_type;
804684ddb6SLionel Sambuc
814684ddb6SLionel Sambuc    // Shared locking
824684ddb6SLionel Sambuc    shared_lock() noexcept;
834684ddb6SLionel Sambuc    explicit shared_lock(mutex_type& m); // blocking
844684ddb6SLionel Sambuc    shared_lock(mutex_type& m, defer_lock_t) noexcept;
854684ddb6SLionel Sambuc    shared_lock(mutex_type& m, try_to_lock_t);
864684ddb6SLionel Sambuc    shared_lock(mutex_type& m, adopt_lock_t);
874684ddb6SLionel Sambuc    template <class Clock, class Duration>
884684ddb6SLionel Sambuc        shared_lock(mutex_type& m,
894684ddb6SLionel Sambuc                    const chrono::time_point<Clock, Duration>& abs_time);
904684ddb6SLionel Sambuc    template <class Rep, class Period>
914684ddb6SLionel Sambuc        shared_lock(mutex_type& m,
924684ddb6SLionel Sambuc                    const chrono::duration<Rep, Period>& rel_time);
934684ddb6SLionel Sambuc    ~shared_lock();
944684ddb6SLionel Sambuc
954684ddb6SLionel Sambuc    shared_lock(shared_lock const&) = delete;
964684ddb6SLionel Sambuc    shared_lock& operator=(shared_lock const&) = delete;
974684ddb6SLionel Sambuc
984684ddb6SLionel Sambuc    shared_lock(shared_lock&& u) noexcept;
994684ddb6SLionel Sambuc    shared_lock& operator=(shared_lock&& u) noexcept;
1004684ddb6SLionel Sambuc
1014684ddb6SLionel Sambuc    void lock(); // blocking
1024684ddb6SLionel Sambuc    bool try_lock();
1034684ddb6SLionel Sambuc    template <class Rep, class Period>
1044684ddb6SLionel Sambuc        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1054684ddb6SLionel Sambuc    template <class Clock, class Duration>
1064684ddb6SLionel Sambuc        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1074684ddb6SLionel Sambuc    void unlock();
1084684ddb6SLionel Sambuc
1094684ddb6SLionel Sambuc    // Setters
1104684ddb6SLionel Sambuc    void swap(shared_lock& u) noexcept;
1114684ddb6SLionel Sambuc    mutex_type* release() noexcept;
1124684ddb6SLionel Sambuc
1134684ddb6SLionel Sambuc    // Getters
1144684ddb6SLionel Sambuc    bool owns_lock() const noexcept;
1154684ddb6SLionel Sambuc    explicit operator bool () const noexcept;
1164684ddb6SLionel Sambuc    mutex_type* mutex() const noexcept;
1174684ddb6SLionel Sambuc};
1184684ddb6SLionel Sambuc
1194684ddb6SLionel Sambuctemplate <class Mutex>
1204684ddb6SLionel Sambuc    void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
1214684ddb6SLionel Sambuc
1224684ddb6SLionel Sambuc}  // std
1234684ddb6SLionel Sambuc
1244684ddb6SLionel Sambuc*/
1254684ddb6SLionel Sambuc
1264684ddb6SLionel Sambuc#include <__config>
1274684ddb6SLionel Sambuc
1284684ddb6SLionel Sambuc#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_SHARED_MUTEX)
1294684ddb6SLionel Sambuc
1304684ddb6SLionel Sambuc#include <__mutex_base>
1314684ddb6SLionel Sambuc
1324684ddb6SLionel Sambuc#include <__undef_min_max>
1334684ddb6SLionel Sambuc
1344684ddb6SLionel Sambuc#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1354684ddb6SLionel Sambuc#pragma GCC system_header
1364684ddb6SLionel Sambuc#endif
1374684ddb6SLionel Sambuc
138*0a6a1f1dSLionel Sambuc#ifdef _LIBCPP_HAS_NO_THREADS
139*0a6a1f1dSLionel Sambuc#error <shared_mutex> is not supported on this single threaded system
140*0a6a1f1dSLionel Sambuc#else // !_LIBCPP_HAS_NO_THREADS
141*0a6a1f1dSLionel Sambuc
1424684ddb6SLionel Sambuc_LIBCPP_BEGIN_NAMESPACE_STD
1434684ddb6SLionel Sambuc
144*0a6a1f1dSLionel Sambucstruct _LIBCPP_TYPE_VIS __shared_mutex_base
1454684ddb6SLionel Sambuc{
1464684ddb6SLionel Sambuc    mutex               __mut_;
1474684ddb6SLionel Sambuc    condition_variable  __gate1_;
1484684ddb6SLionel Sambuc    condition_variable  __gate2_;
1494684ddb6SLionel Sambuc    unsigned            __state_;
1504684ddb6SLionel Sambuc
1514684ddb6SLionel Sambuc    static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
1524684ddb6SLionel Sambuc    static const unsigned __n_readers_ = ~__write_entered_;
153*0a6a1f1dSLionel Sambuc
154*0a6a1f1dSLionel Sambuc    __shared_mutex_base();
155*0a6a1f1dSLionel Sambuc    _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default;
156*0a6a1f1dSLionel Sambuc
157*0a6a1f1dSLionel Sambuc    __shared_mutex_base(const __shared_mutex_base&) = delete;
158*0a6a1f1dSLionel Sambuc    __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;
159*0a6a1f1dSLionel Sambuc
160*0a6a1f1dSLionel Sambuc    // Exclusive ownership
161*0a6a1f1dSLionel Sambuc    void lock(); // blocking
162*0a6a1f1dSLionel Sambuc    bool try_lock();
163*0a6a1f1dSLionel Sambuc    void unlock();
164*0a6a1f1dSLionel Sambuc
165*0a6a1f1dSLionel Sambuc    // Shared ownership
166*0a6a1f1dSLionel Sambuc    void lock_shared(); // blocking
167*0a6a1f1dSLionel Sambuc    bool try_lock_shared();
168*0a6a1f1dSLionel Sambuc    void unlock_shared();
169*0a6a1f1dSLionel Sambuc
170*0a6a1f1dSLionel Sambuc//     typedef implementation-defined native_handle_type; // See 30.2.3
171*0a6a1f1dSLionel Sambuc//     native_handle_type native_handle(); // See 30.2.3
172*0a6a1f1dSLionel Sambuc};
173*0a6a1f1dSLionel Sambuc
174*0a6a1f1dSLionel Sambuc
175*0a6a1f1dSLionel Sambuc#if _LIBCPP_STD_VER > 14
176*0a6a1f1dSLionel Sambucclass _LIBCPP_TYPE_VIS shared_mutex
177*0a6a1f1dSLionel Sambuc{
178*0a6a1f1dSLionel Sambuc	__shared_mutex_base __base;
1794684ddb6SLionel Sambucpublic:
180*0a6a1f1dSLionel Sambuc    shared_mutex() : __base() {}
1814684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
1824684ddb6SLionel Sambuc
1834684ddb6SLionel Sambuc    shared_mutex(const shared_mutex&) = delete;
1844684ddb6SLionel Sambuc    shared_mutex& operator=(const shared_mutex&) = delete;
1854684ddb6SLionel Sambuc
1864684ddb6SLionel Sambuc    // Exclusive ownership
187*0a6a1f1dSLionel Sambuc    _LIBCPP_INLINE_VISIBILITY void lock()     { return __base.lock(); }
188*0a6a1f1dSLionel Sambuc    _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }
189*0a6a1f1dSLionel Sambuc    _LIBCPP_INLINE_VISIBILITY void unlock()   { return __base.unlock(); }
190*0a6a1f1dSLionel Sambuc
191*0a6a1f1dSLionel Sambuc    // Shared ownership
192*0a6a1f1dSLionel Sambuc    _LIBCPP_INLINE_VISIBILITY void lock_shared()     { return __base.lock_shared(); }
193*0a6a1f1dSLionel Sambuc    _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }
194*0a6a1f1dSLionel Sambuc    _LIBCPP_INLINE_VISIBILITY void unlock_shared()   { return __base.unlock_shared(); }
195*0a6a1f1dSLionel Sambuc
196*0a6a1f1dSLionel Sambuc//     typedef __shared_mutex_base::native_handle_type native_handle_type;
197*0a6a1f1dSLionel Sambuc//     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); }
198*0a6a1f1dSLionel Sambuc};
199*0a6a1f1dSLionel Sambuc#endif
200*0a6a1f1dSLionel Sambuc
201*0a6a1f1dSLionel Sambuc
202*0a6a1f1dSLionel Sambucclass _LIBCPP_TYPE_VIS shared_timed_mutex
203*0a6a1f1dSLionel Sambuc{
204*0a6a1f1dSLionel Sambuc	__shared_mutex_base __base;
205*0a6a1f1dSLionel Sambucpublic:
206*0a6a1f1dSLionel Sambuc    shared_timed_mutex();
207*0a6a1f1dSLionel Sambuc    _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;
208*0a6a1f1dSLionel Sambuc
209*0a6a1f1dSLionel Sambuc    shared_timed_mutex(const shared_timed_mutex&) = delete;
210*0a6a1f1dSLionel Sambuc    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
211*0a6a1f1dSLionel Sambuc
212*0a6a1f1dSLionel Sambuc    // Exclusive ownership
2134684ddb6SLionel Sambuc    void lock();
2144684ddb6SLionel Sambuc    bool try_lock();
2154684ddb6SLionel Sambuc    template <class _Rep, class _Period>
2164684ddb6SLionel Sambuc        _LIBCPP_INLINE_VISIBILITY
2174684ddb6SLionel Sambuc        bool
2184684ddb6SLionel Sambuc        try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
2194684ddb6SLionel Sambuc        {
2204684ddb6SLionel Sambuc            return try_lock_until(chrono::steady_clock::now() + __rel_time);
2214684ddb6SLionel Sambuc        }
2224684ddb6SLionel Sambuc    template <class _Clock, class _Duration>
2234684ddb6SLionel Sambuc        bool
2244684ddb6SLionel Sambuc        try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
2254684ddb6SLionel Sambuc    void unlock();
2264684ddb6SLionel Sambuc
2274684ddb6SLionel Sambuc    // Shared ownership
2284684ddb6SLionel Sambuc    void lock_shared();
2294684ddb6SLionel Sambuc    bool try_lock_shared();
2304684ddb6SLionel Sambuc    template <class _Rep, class _Period>
2314684ddb6SLionel Sambuc        _LIBCPP_INLINE_VISIBILITY
2324684ddb6SLionel Sambuc        bool
2334684ddb6SLionel Sambuc        try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
2344684ddb6SLionel Sambuc        {
2354684ddb6SLionel Sambuc            return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
2364684ddb6SLionel Sambuc        }
2374684ddb6SLionel Sambuc    template <class _Clock, class _Duration>
2384684ddb6SLionel Sambuc        bool
2394684ddb6SLionel Sambuc        try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
2404684ddb6SLionel Sambuc    void unlock_shared();
2414684ddb6SLionel Sambuc};
2424684ddb6SLionel Sambuc
2434684ddb6SLionel Sambuctemplate <class _Clock, class _Duration>
2444684ddb6SLionel Sambucbool
245*0a6a1f1dSLionel Sambucshared_timed_mutex::try_lock_until(
2464684ddb6SLionel Sambuc                        const chrono::time_point<_Clock, _Duration>& __abs_time)
2474684ddb6SLionel Sambuc{
248*0a6a1f1dSLionel Sambuc    unique_lock<mutex> __lk(__base.__mut_);
249*0a6a1f1dSLionel Sambuc    if (__base.__state_ & __base.__write_entered_)
2504684ddb6SLionel Sambuc    {
2514684ddb6SLionel Sambuc        while (true)
2524684ddb6SLionel Sambuc        {
253*0a6a1f1dSLionel Sambuc            cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time);
254*0a6a1f1dSLionel Sambuc            if ((__base.__state_ & __base.__write_entered_) == 0)
2554684ddb6SLionel Sambuc                break;
2564684ddb6SLionel Sambuc            if (__status == cv_status::timeout)
2574684ddb6SLionel Sambuc                return false;
2584684ddb6SLionel Sambuc        }
2594684ddb6SLionel Sambuc    }
260*0a6a1f1dSLionel Sambuc    __base.__state_ |= __base.__write_entered_;
261*0a6a1f1dSLionel Sambuc    if (__base.__state_ & __base.__n_readers_)
2624684ddb6SLionel Sambuc    {
2634684ddb6SLionel Sambuc        while (true)
2644684ddb6SLionel Sambuc        {
265*0a6a1f1dSLionel Sambuc            cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time);
266*0a6a1f1dSLionel Sambuc            if ((__base.__state_ & __base.__n_readers_) == 0)
2674684ddb6SLionel Sambuc                break;
2684684ddb6SLionel Sambuc            if (__status == cv_status::timeout)
2694684ddb6SLionel Sambuc            {
270*0a6a1f1dSLionel Sambuc                __base.__state_ &= ~__base.__write_entered_;
271*0a6a1f1dSLionel Sambuc                __base.__gate1_.notify_all();
2724684ddb6SLionel Sambuc                return false;
2734684ddb6SLionel Sambuc            }
2744684ddb6SLionel Sambuc        }
2754684ddb6SLionel Sambuc    }
2764684ddb6SLionel Sambuc    return true;
2774684ddb6SLionel Sambuc}
2784684ddb6SLionel Sambuc
2794684ddb6SLionel Sambuctemplate <class _Clock, class _Duration>
2804684ddb6SLionel Sambucbool
281*0a6a1f1dSLionel Sambucshared_timed_mutex::try_lock_shared_until(
2824684ddb6SLionel Sambuc                        const chrono::time_point<_Clock, _Duration>& __abs_time)
2834684ddb6SLionel Sambuc{
284*0a6a1f1dSLionel Sambuc    unique_lock<mutex> __lk(__base.__mut_);
285*0a6a1f1dSLionel Sambuc    if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_)
2864684ddb6SLionel Sambuc    {
2874684ddb6SLionel Sambuc        while (true)
2884684ddb6SLionel Sambuc        {
289*0a6a1f1dSLionel Sambuc            cv_status status = __base.__gate1_.wait_until(__lk, __abs_time);
290*0a6a1f1dSLionel Sambuc            if ((__base.__state_ & __base.__write_entered_) == 0 &&
291*0a6a1f1dSLionel Sambuc                                       (__base.__state_ & __base.__n_readers_) < __base.__n_readers_)
2924684ddb6SLionel Sambuc                break;
2934684ddb6SLionel Sambuc            if (status == cv_status::timeout)
2944684ddb6SLionel Sambuc                return false;
2954684ddb6SLionel Sambuc        }
2964684ddb6SLionel Sambuc    }
297*0a6a1f1dSLionel Sambuc    unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1;
298*0a6a1f1dSLionel Sambuc    __base.__state_ &= ~__base.__n_readers_;
299*0a6a1f1dSLionel Sambuc    __base.__state_ |= __num_readers;
3004684ddb6SLionel Sambuc    return true;
3014684ddb6SLionel Sambuc}
3024684ddb6SLionel Sambuc
3034684ddb6SLionel Sambuctemplate <class _Mutex>
3044684ddb6SLionel Sambucclass shared_lock
3054684ddb6SLionel Sambuc{
3064684ddb6SLionel Sambucpublic:
3074684ddb6SLionel Sambuc    typedef _Mutex mutex_type;
3084684ddb6SLionel Sambuc
3094684ddb6SLionel Sambucprivate:
3104684ddb6SLionel Sambuc    mutex_type* __m_;
3114684ddb6SLionel Sambuc    bool __owns_;
3124684ddb6SLionel Sambuc
3134684ddb6SLionel Sambucpublic:
3144684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
315*0a6a1f1dSLionel Sambuc    shared_lock() _NOEXCEPT
3164684ddb6SLionel Sambuc        : __m_(nullptr),
3174684ddb6SLionel Sambuc          __owns_(false)
3184684ddb6SLionel Sambuc        {}
3194684ddb6SLionel Sambuc
3204684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
3214684ddb6SLionel Sambuc    explicit shared_lock(mutex_type& __m)
3224684ddb6SLionel Sambuc        : __m_(&__m),
3234684ddb6SLionel Sambuc          __owns_(true)
3244684ddb6SLionel Sambuc        {__m_->lock_shared();}
3254684ddb6SLionel Sambuc
3264684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
327*0a6a1f1dSLionel Sambuc    shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
3284684ddb6SLionel Sambuc        : __m_(&__m),
3294684ddb6SLionel Sambuc          __owns_(false)
3304684ddb6SLionel Sambuc        {}
3314684ddb6SLionel Sambuc
3324684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
3334684ddb6SLionel Sambuc    shared_lock(mutex_type& __m, try_to_lock_t)
3344684ddb6SLionel Sambuc        : __m_(&__m),
3354684ddb6SLionel Sambuc          __owns_(__m.try_lock_shared())
3364684ddb6SLionel Sambuc        {}
3374684ddb6SLionel Sambuc
3384684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
3394684ddb6SLionel Sambuc    shared_lock(mutex_type& __m, adopt_lock_t)
3404684ddb6SLionel Sambuc        : __m_(&__m),
3414684ddb6SLionel Sambuc          __owns_(true)
3424684ddb6SLionel Sambuc        {}
3434684ddb6SLionel Sambuc
3444684ddb6SLionel Sambuc    template <class _Clock, class _Duration>
3454684ddb6SLionel Sambuc        _LIBCPP_INLINE_VISIBILITY
3464684ddb6SLionel Sambuc        shared_lock(mutex_type& __m,
3474684ddb6SLionel Sambuc                    const chrono::time_point<_Clock, _Duration>& __abs_time)
3484684ddb6SLionel Sambuc            : __m_(&__m),
3494684ddb6SLionel Sambuc              __owns_(__m.try_lock_shared_until(__abs_time))
3504684ddb6SLionel Sambuc            {}
3514684ddb6SLionel Sambuc
3524684ddb6SLionel Sambuc    template <class _Rep, class _Period>
3534684ddb6SLionel Sambuc        _LIBCPP_INLINE_VISIBILITY
3544684ddb6SLionel Sambuc        shared_lock(mutex_type& __m,
3554684ddb6SLionel Sambuc                    const chrono::duration<_Rep, _Period>& __rel_time)
3564684ddb6SLionel Sambuc            : __m_(&__m),
3574684ddb6SLionel Sambuc              __owns_(__m.try_lock_shared_for(__rel_time))
3584684ddb6SLionel Sambuc            {}
3594684ddb6SLionel Sambuc
3604684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
3614684ddb6SLionel Sambuc    ~shared_lock()
3624684ddb6SLionel Sambuc    {
3634684ddb6SLionel Sambuc        if (__owns_)
3644684ddb6SLionel Sambuc            __m_->unlock_shared();
3654684ddb6SLionel Sambuc    }
3664684ddb6SLionel Sambuc
3674684ddb6SLionel Sambuc    shared_lock(shared_lock const&) = delete;
3684684ddb6SLionel Sambuc    shared_lock& operator=(shared_lock const&) = delete;
3694684ddb6SLionel Sambuc
3704684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
371*0a6a1f1dSLionel Sambuc    shared_lock(shared_lock&& __u) _NOEXCEPT
3724684ddb6SLionel Sambuc        : __m_(__u.__m_),
3734684ddb6SLionel Sambuc          __owns_(__u.__owns_)
3744684ddb6SLionel Sambuc        {
3754684ddb6SLionel Sambuc            __u.__m_ = nullptr;
3764684ddb6SLionel Sambuc            __u.__owns_ = false;
3774684ddb6SLionel Sambuc        }
3784684ddb6SLionel Sambuc
3794684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
380*0a6a1f1dSLionel Sambuc    shared_lock& operator=(shared_lock&& __u) _NOEXCEPT
3814684ddb6SLionel Sambuc    {
3824684ddb6SLionel Sambuc        if (__owns_)
3834684ddb6SLionel Sambuc            __m_->unlock_shared();
3844684ddb6SLionel Sambuc        __m_ = nullptr;
3854684ddb6SLionel Sambuc        __owns_ = false;
3864684ddb6SLionel Sambuc        __m_ = __u.__m_;
3874684ddb6SLionel Sambuc        __owns_ = __u.__owns_;
3884684ddb6SLionel Sambuc        __u.__m_ = nullptr;
3894684ddb6SLionel Sambuc        __u.__owns_ = false;
3904684ddb6SLionel Sambuc        return *this;
3914684ddb6SLionel Sambuc    }
3924684ddb6SLionel Sambuc
3934684ddb6SLionel Sambuc    void lock();
3944684ddb6SLionel Sambuc    bool try_lock();
3954684ddb6SLionel Sambuc    template <class Rep, class Period>
3964684ddb6SLionel Sambuc        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
3974684ddb6SLionel Sambuc    template <class Clock, class Duration>
3984684ddb6SLionel Sambuc        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
3994684ddb6SLionel Sambuc    void unlock();
4004684ddb6SLionel Sambuc
4014684ddb6SLionel Sambuc    // Setters
4024684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
403*0a6a1f1dSLionel Sambuc    void swap(shared_lock& __u) _NOEXCEPT
4044684ddb6SLionel Sambuc    {
4054684ddb6SLionel Sambuc        _VSTD::swap(__m_, __u.__m_);
4064684ddb6SLionel Sambuc        _VSTD::swap(__owns_, __u.__owns_);
4074684ddb6SLionel Sambuc    }
4084684ddb6SLionel Sambuc
4094684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
410*0a6a1f1dSLionel Sambuc    mutex_type* release() _NOEXCEPT
4114684ddb6SLionel Sambuc    {
4124684ddb6SLionel Sambuc        mutex_type* __m = __m_;
4134684ddb6SLionel Sambuc        __m_ = nullptr;
4144684ddb6SLionel Sambuc        __owns_ = false;
4154684ddb6SLionel Sambuc        return __m;
4164684ddb6SLionel Sambuc    }
4174684ddb6SLionel Sambuc
4184684ddb6SLionel Sambuc    // Getters
4194684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
420*0a6a1f1dSLionel Sambuc    bool owns_lock() const _NOEXCEPT {return __owns_;}
4214684ddb6SLionel Sambuc
4224684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
423*0a6a1f1dSLionel Sambuc    explicit operator bool () const _NOEXCEPT {return __owns_;}
4244684ddb6SLionel Sambuc
4254684ddb6SLionel Sambuc    _LIBCPP_INLINE_VISIBILITY
426*0a6a1f1dSLionel Sambuc    mutex_type* mutex() const _NOEXCEPT {return __m_;}
4274684ddb6SLionel Sambuc};
4284684ddb6SLionel Sambuc
4294684ddb6SLionel Sambuctemplate <class _Mutex>
4304684ddb6SLionel Sambucvoid
4314684ddb6SLionel Sambucshared_lock<_Mutex>::lock()
4324684ddb6SLionel Sambuc{
4334684ddb6SLionel Sambuc    if (__m_ == nullptr)
4344684ddb6SLionel Sambuc        __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
4354684ddb6SLionel Sambuc    if (__owns_)
4364684ddb6SLionel Sambuc        __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
4374684ddb6SLionel Sambuc    __m_->lock_shared();
4384684ddb6SLionel Sambuc    __owns_ = true;
4394684ddb6SLionel Sambuc}
4404684ddb6SLionel Sambuc
4414684ddb6SLionel Sambuctemplate <class _Mutex>
4424684ddb6SLionel Sambucbool
4434684ddb6SLionel Sambucshared_lock<_Mutex>::try_lock()
4444684ddb6SLionel Sambuc{
4454684ddb6SLionel Sambuc    if (__m_ == nullptr)
4464684ddb6SLionel Sambuc        __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
4474684ddb6SLionel Sambuc    if (__owns_)
4484684ddb6SLionel Sambuc        __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
4494684ddb6SLionel Sambuc    __owns_ = __m_->try_lock_shared();
4504684ddb6SLionel Sambuc    return __owns_;
4514684ddb6SLionel Sambuc}
4524684ddb6SLionel Sambuc
4534684ddb6SLionel Sambuctemplate <class _Mutex>
4544684ddb6SLionel Sambuctemplate <class _Rep, class _Period>
4554684ddb6SLionel Sambucbool
4564684ddb6SLionel Sambucshared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
4574684ddb6SLionel Sambuc{
4584684ddb6SLionel Sambuc    if (__m_ == nullptr)
4594684ddb6SLionel Sambuc        __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
4604684ddb6SLionel Sambuc    if (__owns_)
4614684ddb6SLionel Sambuc        __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
4624684ddb6SLionel Sambuc    __owns_ = __m_->try_lock_shared_for(__d);
4634684ddb6SLionel Sambuc    return __owns_;
4644684ddb6SLionel Sambuc}
4654684ddb6SLionel Sambuc
4664684ddb6SLionel Sambuctemplate <class _Mutex>
4674684ddb6SLionel Sambuctemplate <class _Clock, class _Duration>
4684684ddb6SLionel Sambucbool
4694684ddb6SLionel Sambucshared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
4704684ddb6SLionel Sambuc{
4714684ddb6SLionel Sambuc    if (__m_ == nullptr)
4724684ddb6SLionel Sambuc        __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
4734684ddb6SLionel Sambuc    if (__owns_)
4744684ddb6SLionel Sambuc        __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
4754684ddb6SLionel Sambuc    __owns_ = __m_->try_lock_shared_until(__t);
4764684ddb6SLionel Sambuc    return __owns_;
4774684ddb6SLionel Sambuc}
4784684ddb6SLionel Sambuc
4794684ddb6SLionel Sambuctemplate <class _Mutex>
4804684ddb6SLionel Sambucvoid
4814684ddb6SLionel Sambucshared_lock<_Mutex>::unlock()
4824684ddb6SLionel Sambuc{
4834684ddb6SLionel Sambuc    if (!__owns_)
4844684ddb6SLionel Sambuc        __throw_system_error(EPERM, "shared_lock::unlock: not locked");
4854684ddb6SLionel Sambuc    __m_->unlock_shared();
4864684ddb6SLionel Sambuc    __owns_ = false;
4874684ddb6SLionel Sambuc}
4884684ddb6SLionel Sambuc
4894684ddb6SLionel Sambuctemplate <class _Mutex>
4904684ddb6SLionel Sambucinline _LIBCPP_INLINE_VISIBILITY
4914684ddb6SLionel Sambucvoid
492*0a6a1f1dSLionel Sambucswap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT
4934684ddb6SLionel Sambuc    {__x.swap(__y);}
4944684ddb6SLionel Sambuc
4954684ddb6SLionel Sambuc_LIBCPP_END_NAMESPACE_STD
4964684ddb6SLionel Sambuc
497*0a6a1f1dSLionel Sambuc#endif  // !_LIBCPP_HAS_NO_THREADS
498*0a6a1f1dSLionel Sambuc
4994684ddb6SLionel Sambuc#endif  // _LIBCPP_STD_VER > 11
5004684ddb6SLionel Sambuc
5014684ddb6SLionel Sambuc#endif  // _LIBCPP_SHARED_MUTEX
502