1ead6f169SHoward Hinnant// -*- C++ -*-
2ead6f169SHoward Hinnant//===------------------------ shared_mutex --------------------------------===//
3ead6f169SHoward Hinnant//
4ead6f169SHoward Hinnant//                     The LLVM Compiler Infrastructure
5ead6f169SHoward Hinnant//
6ead6f169SHoward Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
7ead6f169SHoward Hinnant// Source Licenses. See LICENSE.TXT for details.
8ead6f169SHoward Hinnant//
9ead6f169SHoward Hinnant//===----------------------------------------------------------------------===//
10ead6f169SHoward Hinnant
11ead6f169SHoward Hinnant#ifndef _LIBCPP_SHARED_MUTEX
12ead6f169SHoward Hinnant#define _LIBCPP_SHARED_MUTEX
13ead6f169SHoward Hinnant
14ead6f169SHoward Hinnant/*
15ead6f169SHoward Hinnant    shared_mutex synopsis
16ead6f169SHoward Hinnant
17ead6f169SHoward Hinnant// C++1y
18ead6f169SHoward Hinnant
19ead6f169SHoward Hinnantnamespace std
20ead6f169SHoward Hinnant{
21ead6f169SHoward Hinnant
22f69ae471SMarshall Clowclass shared_mutex      // C++17
23f69ae471SMarshall Clow{
24f69ae471SMarshall Clowpublic:
25f69ae471SMarshall Clow    shared_mutex();
26f69ae471SMarshall Clow    ~shared_mutex();
27f69ae471SMarshall Clow
28f69ae471SMarshall Clow    shared_mutex(const shared_mutex&) = delete;
29f69ae471SMarshall Clow    shared_mutex& operator=(const shared_mutex&) = delete;
30f69ae471SMarshall Clow
31f69ae471SMarshall Clow    // Exclusive ownership
32f69ae471SMarshall Clow    void lock(); // blocking
33f69ae471SMarshall Clow    bool try_lock();
34f69ae471SMarshall Clow    void unlock();
35f69ae471SMarshall Clow
36f69ae471SMarshall Clow    // Shared ownership
37f69ae471SMarshall Clow    void lock_shared(); // blocking
38f69ae471SMarshall Clow    bool try_lock_shared();
39f69ae471SMarshall Clow    void unlock_shared();
40f69ae471SMarshall Clow
41f69ae471SMarshall Clow    typedef implementation-defined native_handle_type; // See 30.2.3
42f69ae471SMarshall Clow    native_handle_type native_handle(); // See 30.2.3
43f69ae471SMarshall Clow};
44f69ae471SMarshall Clow
457ec93f9bSDavid Majnemerclass shared_timed_mutex
46ead6f169SHoward Hinnant{
47ead6f169SHoward Hinnantpublic:
487ec93f9bSDavid Majnemer    shared_timed_mutex();
497ec93f9bSDavid Majnemer    ~shared_timed_mutex();
50ead6f169SHoward Hinnant
517ec93f9bSDavid Majnemer    shared_timed_mutex(const shared_timed_mutex&) = delete;
527ec93f9bSDavid Majnemer    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
53ead6f169SHoward Hinnant
54ead6f169SHoward Hinnant    // Exclusive ownership
55ead6f169SHoward Hinnant    void lock(); // blocking
56ead6f169SHoward Hinnant    bool try_lock();
57ead6f169SHoward Hinnant    template <class Rep, class Period>
58ead6f169SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
59ead6f169SHoward Hinnant    template <class Clock, class Duration>
60ead6f169SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
61ead6f169SHoward Hinnant    void unlock();
62ead6f169SHoward Hinnant
63ead6f169SHoward Hinnant    // Shared ownership
64ead6f169SHoward Hinnant    void lock_shared(); // blocking
65ead6f169SHoward Hinnant    bool try_lock_shared();
66ead6f169SHoward Hinnant    template <class Rep, class Period>
67ead6f169SHoward Hinnant        bool
68ead6f169SHoward Hinnant        try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
69ead6f169SHoward Hinnant    template <class Clock, class Duration>
70ead6f169SHoward Hinnant        bool
71ead6f169SHoward Hinnant        try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
72ead6f169SHoward Hinnant    void unlock_shared();
73ead6f169SHoward Hinnant};
74ead6f169SHoward Hinnant
75ead6f169SHoward Hinnanttemplate <class Mutex>
76ead6f169SHoward Hinnantclass shared_lock
77ead6f169SHoward Hinnant{
78ead6f169SHoward Hinnantpublic:
79ead6f169SHoward Hinnant    typedef Mutex mutex_type;
80ead6f169SHoward Hinnant
81ead6f169SHoward Hinnant    // Shared locking
82ead6f169SHoward Hinnant    shared_lock() noexcept;
83ead6f169SHoward Hinnant    explicit shared_lock(mutex_type& m); // blocking
84ead6f169SHoward Hinnant    shared_lock(mutex_type& m, defer_lock_t) noexcept;
85ead6f169SHoward Hinnant    shared_lock(mutex_type& m, try_to_lock_t);
86ead6f169SHoward Hinnant    shared_lock(mutex_type& m, adopt_lock_t);
87ead6f169SHoward Hinnant    template <class Clock, class Duration>
88ead6f169SHoward Hinnant        shared_lock(mutex_type& m,
89ead6f169SHoward Hinnant                    const chrono::time_point<Clock, Duration>& abs_time);
90ead6f169SHoward Hinnant    template <class Rep, class Period>
91ead6f169SHoward Hinnant        shared_lock(mutex_type& m,
92ead6f169SHoward Hinnant                    const chrono::duration<Rep, Period>& rel_time);
93ead6f169SHoward Hinnant    ~shared_lock();
94ead6f169SHoward Hinnant
95ead6f169SHoward Hinnant    shared_lock(shared_lock const&) = delete;
96ead6f169SHoward Hinnant    shared_lock& operator=(shared_lock const&) = delete;
97ead6f169SHoward Hinnant
98ead6f169SHoward Hinnant    shared_lock(shared_lock&& u) noexcept;
99ead6f169SHoward Hinnant    shared_lock& operator=(shared_lock&& u) noexcept;
100ead6f169SHoward Hinnant
101ead6f169SHoward Hinnant    void lock(); // blocking
102ead6f169SHoward Hinnant    bool try_lock();
103ead6f169SHoward Hinnant    template <class Rep, class Period>
104ead6f169SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
105ead6f169SHoward Hinnant    template <class Clock, class Duration>
106ead6f169SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
107ead6f169SHoward Hinnant    void unlock();
108ead6f169SHoward Hinnant
109ead6f169SHoward Hinnant    // Setters
110ead6f169SHoward Hinnant    void swap(shared_lock& u) noexcept;
111ead6f169SHoward Hinnant    mutex_type* release() noexcept;
112ead6f169SHoward Hinnant
113ead6f169SHoward Hinnant    // Getters
114ead6f169SHoward Hinnant    bool owns_lock() const noexcept;
115ead6f169SHoward Hinnant    explicit operator bool () const noexcept;
116ead6f169SHoward Hinnant    mutex_type* mutex() const noexcept;
117ead6f169SHoward Hinnant};
118ead6f169SHoward Hinnant
119ead6f169SHoward Hinnanttemplate <class Mutex>
120ead6f169SHoward Hinnant    void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
121ead6f169SHoward Hinnant
122ead6f169SHoward Hinnant}  // std
123ead6f169SHoward Hinnant
124ead6f169SHoward Hinnant*/
125ead6f169SHoward Hinnant
126ead6f169SHoward Hinnant#include <__config>
127*f56972e2SMarshall Clow#include <version>
128ead6f169SHoward Hinnant
129a016efb1SEric Fiselier_LIBCPP_PUSH_MACROS
130a016efb1SEric Fiselier#include <__undef_macros>
131a016efb1SEric Fiselier
132a016efb1SEric Fiselier
133c8e84ff2SLouis Dionne#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_LIBRARY)
134ead6f169SHoward Hinnant
135ead6f169SHoward Hinnant#include <__mutex_base>
136ead6f169SHoward Hinnant
137ead6f169SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
138ead6f169SHoward Hinnant#pragma GCC system_header
139ead6f169SHoward Hinnant#endif
140ead6f169SHoward Hinnant
141b3fcc67fSJonathan Roelofs#ifdef _LIBCPP_HAS_NO_THREADS
142b3fcc67fSJonathan Roelofs#error <shared_mutex> is not supported on this single threaded system
143b3fcc67fSJonathan Roelofs#else // !_LIBCPP_HAS_NO_THREADS
144b3fcc67fSJonathan Roelofs
145ead6f169SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD
146ead6f169SHoward Hinnant
147e9c66ad9SMehdi Aministruct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX __shared_mutex_base
148ead6f169SHoward Hinnant{
149ead6f169SHoward Hinnant    mutex               __mut_;
150ead6f169SHoward Hinnant    condition_variable  __gate1_;
151ead6f169SHoward Hinnant    condition_variable  __gate2_;
152ead6f169SHoward Hinnant    unsigned            __state_;
153ead6f169SHoward Hinnant
154ead6f169SHoward Hinnant    static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
155ead6f169SHoward Hinnant    static const unsigned __n_readers_ = ~__write_entered_;
156f69ae471SMarshall Clow
157f69ae471SMarshall Clow    __shared_mutex_base();
158f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default;
159f69ae471SMarshall Clow
160f69ae471SMarshall Clow    __shared_mutex_base(const __shared_mutex_base&) = delete;
161f69ae471SMarshall Clow    __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;
162f69ae471SMarshall Clow
163f69ae471SMarshall Clow    // Exclusive ownership
164f69ae471SMarshall Clow    void lock(); // blocking
165f69ae471SMarshall Clow    bool try_lock();
166f69ae471SMarshall Clow    void unlock();
167f69ae471SMarshall Clow
168f69ae471SMarshall Clow    // Shared ownership
169f69ae471SMarshall Clow    void lock_shared(); // blocking
170f69ae471SMarshall Clow    bool try_lock_shared();
171f69ae471SMarshall Clow    void unlock_shared();
172f69ae471SMarshall Clow
173f69ae471SMarshall Clow//     typedef implementation-defined native_handle_type; // See 30.2.3
174f69ae471SMarshall Clow//     native_handle_type native_handle(); // See 30.2.3
175f69ae471SMarshall Clow};
176f69ae471SMarshall Clow
177f69ae471SMarshall Clow
178f69ae471SMarshall Clow#if _LIBCPP_STD_VER > 14
179e9c66ad9SMehdi Aminiclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex
180f69ae471SMarshall Clow{
181f69ae471SMarshall Clow    __shared_mutex_base __base;
182f69ae471SMarshall Clowpublic:
183ef407482SEric Fiselier    _LIBCPP_INLINE_VISIBILITY shared_mutex() : __base() {}
184f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
185f69ae471SMarshall Clow
186f69ae471SMarshall Clow    shared_mutex(const shared_mutex&) = delete;
187f69ae471SMarshall Clow    shared_mutex& operator=(const shared_mutex&) = delete;
188f69ae471SMarshall Clow
189f69ae471SMarshall Clow    // Exclusive ownership
190f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY void lock()     { return __base.lock(); }
191f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }
192f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY void unlock()   { return __base.unlock(); }
193f69ae471SMarshall Clow
194f69ae471SMarshall Clow    // Shared ownership
195f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY void lock_shared()     { return __base.lock_shared(); }
196f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }
197f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY void unlock_shared()   { return __base.unlock_shared(); }
198f69ae471SMarshall Clow
199f69ae471SMarshall Clow//     typedef __shared_mutex_base::native_handle_type native_handle_type;
200f69ae471SMarshall Clow//     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); }
201f69ae471SMarshall Clow};
202f69ae471SMarshall Clow#endif
203f69ae471SMarshall Clow
204f69ae471SMarshall Clow
205e9c66ad9SMehdi Aminiclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_timed_mutex
206f69ae471SMarshall Clow{
207f69ae471SMarshall Clow    __shared_mutex_base __base;
208ead6f169SHoward Hinnantpublic:
2097ec93f9bSDavid Majnemer    shared_timed_mutex();
2107ec93f9bSDavid Majnemer    _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;
211ead6f169SHoward Hinnant
2127ec93f9bSDavid Majnemer    shared_timed_mutex(const shared_timed_mutex&) = delete;
2137ec93f9bSDavid Majnemer    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
214ead6f169SHoward Hinnant
215ead6f169SHoward Hinnant    // Exclusive ownership
216ead6f169SHoward Hinnant    void lock();
217ead6f169SHoward Hinnant    bool try_lock();
218ead6f169SHoward Hinnant    template <class _Rep, class _Period>
219ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
220ead6f169SHoward Hinnant        bool
221ead6f169SHoward Hinnant        try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
222ead6f169SHoward Hinnant        {
223ead6f169SHoward Hinnant            return try_lock_until(chrono::steady_clock::now() + __rel_time);
224ead6f169SHoward Hinnant        }
225ead6f169SHoward Hinnant    template <class _Clock, class _Duration>
226bda3c7dfSShoaib Meenai        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
227ead6f169SHoward Hinnant        bool
228ead6f169SHoward Hinnant        try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
229ead6f169SHoward Hinnant    void unlock();
230ead6f169SHoward Hinnant
231ead6f169SHoward Hinnant    // Shared ownership
232ead6f169SHoward Hinnant    void lock_shared();
233ead6f169SHoward Hinnant    bool try_lock_shared();
234ead6f169SHoward Hinnant    template <class _Rep, class _Period>
235ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
236ead6f169SHoward Hinnant        bool
237ead6f169SHoward Hinnant        try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
238ead6f169SHoward Hinnant        {
239ead6f169SHoward Hinnant            return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
240ead6f169SHoward Hinnant        }
241ead6f169SHoward Hinnant    template <class _Clock, class _Duration>
242bda3c7dfSShoaib Meenai        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
243ead6f169SHoward Hinnant        bool
244ead6f169SHoward Hinnant        try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
245ead6f169SHoward Hinnant    void unlock_shared();
246ead6f169SHoward Hinnant};
247ead6f169SHoward Hinnant
248ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration>
249ead6f169SHoward Hinnantbool
2507ec93f9bSDavid Majnemershared_timed_mutex::try_lock_until(
251ead6f169SHoward Hinnant                        const chrono::time_point<_Clock, _Duration>& __abs_time)
252ead6f169SHoward Hinnant{
253f69ae471SMarshall Clow    unique_lock<mutex> __lk(__base.__mut_);
254f69ae471SMarshall Clow    if (__base.__state_ & __base.__write_entered_)
255ead6f169SHoward Hinnant    {
256ead6f169SHoward Hinnant        while (true)
257ead6f169SHoward Hinnant        {
258f69ae471SMarshall Clow            cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time);
259f69ae471SMarshall Clow            if ((__base.__state_ & __base.__write_entered_) == 0)
260ead6f169SHoward Hinnant                break;
261ead6f169SHoward Hinnant            if (__status == cv_status::timeout)
262ead6f169SHoward Hinnant                return false;
263ead6f169SHoward Hinnant        }
264ead6f169SHoward Hinnant    }
265f69ae471SMarshall Clow    __base.__state_ |= __base.__write_entered_;
266f69ae471SMarshall Clow    if (__base.__state_ & __base.__n_readers_)
267ead6f169SHoward Hinnant    {
268ead6f169SHoward Hinnant        while (true)
269ead6f169SHoward Hinnant        {
270f69ae471SMarshall Clow            cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time);
271f69ae471SMarshall Clow            if ((__base.__state_ & __base.__n_readers_) == 0)
272ead6f169SHoward Hinnant                break;
273ead6f169SHoward Hinnant            if (__status == cv_status::timeout)
274ead6f169SHoward Hinnant            {
275f69ae471SMarshall Clow                __base.__state_ &= ~__base.__write_entered_;
276f69ae471SMarshall Clow                __base.__gate1_.notify_all();
277ead6f169SHoward Hinnant                return false;
278ead6f169SHoward Hinnant            }
279ead6f169SHoward Hinnant        }
280ead6f169SHoward Hinnant    }
281ead6f169SHoward Hinnant    return true;
282ead6f169SHoward Hinnant}
283ead6f169SHoward Hinnant
284ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration>
285ead6f169SHoward Hinnantbool
2867ec93f9bSDavid Majnemershared_timed_mutex::try_lock_shared_until(
287ead6f169SHoward Hinnant                        const chrono::time_point<_Clock, _Duration>& __abs_time)
288ead6f169SHoward Hinnant{
289f69ae471SMarshall Clow    unique_lock<mutex> __lk(__base.__mut_);
290f69ae471SMarshall Clow    if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_)
291ead6f169SHoward Hinnant    {
292ead6f169SHoward Hinnant        while (true)
293ead6f169SHoward Hinnant        {
294f69ae471SMarshall Clow            cv_status status = __base.__gate1_.wait_until(__lk, __abs_time);
295f69ae471SMarshall Clow            if ((__base.__state_ & __base.__write_entered_) == 0 &&
296f69ae471SMarshall Clow                                       (__base.__state_ & __base.__n_readers_) < __base.__n_readers_)
297ead6f169SHoward Hinnant                break;
298ead6f169SHoward Hinnant            if (status == cv_status::timeout)
299ead6f169SHoward Hinnant                return false;
300ead6f169SHoward Hinnant        }
301ead6f169SHoward Hinnant    }
302f69ae471SMarshall Clow    unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1;
303f69ae471SMarshall Clow    __base.__state_ &= ~__base.__n_readers_;
304f69ae471SMarshall Clow    __base.__state_ |= __num_readers;
305ead6f169SHoward Hinnant    return true;
306ead6f169SHoward Hinnant}
307ead6f169SHoward Hinnant
308ead6f169SHoward Hinnanttemplate <class _Mutex>
309ead6f169SHoward Hinnantclass shared_lock
310ead6f169SHoward Hinnant{
311ead6f169SHoward Hinnantpublic:
312ead6f169SHoward Hinnant    typedef _Mutex mutex_type;
313ead6f169SHoward Hinnant
314ead6f169SHoward Hinnantprivate:
315ead6f169SHoward Hinnant    mutex_type* __m_;
316ead6f169SHoward Hinnant    bool __owns_;
317ead6f169SHoward Hinnant
318ead6f169SHoward Hinnantpublic:
319ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
320d08f0d9cSMarshall Clow    shared_lock() _NOEXCEPT
321ead6f169SHoward Hinnant        : __m_(nullptr),
322ead6f169SHoward Hinnant          __owns_(false)
323ead6f169SHoward Hinnant        {}
324ead6f169SHoward Hinnant
325ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
326ead6f169SHoward Hinnant    explicit shared_lock(mutex_type& __m)
3273126c881SMarshall Clow        : __m_(_VSTD::addressof(__m)),
328ead6f169SHoward Hinnant          __owns_(true)
329ead6f169SHoward Hinnant        {__m_->lock_shared();}
330ead6f169SHoward Hinnant
331ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
332d08f0d9cSMarshall Clow    shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
3333126c881SMarshall Clow        : __m_(_VSTD::addressof(__m)),
334ead6f169SHoward Hinnant          __owns_(false)
335ead6f169SHoward Hinnant        {}
336ead6f169SHoward Hinnant
337ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
338ead6f169SHoward Hinnant    shared_lock(mutex_type& __m, try_to_lock_t)
3393126c881SMarshall Clow        : __m_(_VSTD::addressof(__m)),
340ead6f169SHoward Hinnant          __owns_(__m.try_lock_shared())
341ead6f169SHoward Hinnant        {}
342ead6f169SHoward Hinnant
343ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
344ead6f169SHoward Hinnant    shared_lock(mutex_type& __m, adopt_lock_t)
3453126c881SMarshall Clow        : __m_(_VSTD::addressof(__m)),
346ead6f169SHoward Hinnant          __owns_(true)
347ead6f169SHoward Hinnant        {}
348ead6f169SHoward Hinnant
349ead6f169SHoward Hinnant    template <class _Clock, class _Duration>
350ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
351ead6f169SHoward Hinnant        shared_lock(mutex_type& __m,
352ead6f169SHoward Hinnant                    const chrono::time_point<_Clock, _Duration>& __abs_time)
3533126c881SMarshall Clow            : __m_(_VSTD::addressof(__m)),
354ead6f169SHoward Hinnant              __owns_(__m.try_lock_shared_until(__abs_time))
355ead6f169SHoward Hinnant            {}
356ead6f169SHoward Hinnant
357ead6f169SHoward Hinnant    template <class _Rep, class _Period>
358ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
359ead6f169SHoward Hinnant        shared_lock(mutex_type& __m,
360ead6f169SHoward Hinnant                    const chrono::duration<_Rep, _Period>& __rel_time)
3613126c881SMarshall Clow            : __m_(_VSTD::addressof(__m)),
362ead6f169SHoward Hinnant              __owns_(__m.try_lock_shared_for(__rel_time))
363ead6f169SHoward Hinnant            {}
364ead6f169SHoward Hinnant
365ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
366ead6f169SHoward Hinnant    ~shared_lock()
367ead6f169SHoward Hinnant    {
368ead6f169SHoward Hinnant        if (__owns_)
369ead6f169SHoward Hinnant            __m_->unlock_shared();
370ead6f169SHoward Hinnant    }
371ead6f169SHoward Hinnant
372ead6f169SHoward Hinnant    shared_lock(shared_lock const&) = delete;
373ead6f169SHoward Hinnant    shared_lock& operator=(shared_lock const&) = delete;
374ead6f169SHoward Hinnant
375ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
376d08f0d9cSMarshall Clow    shared_lock(shared_lock&& __u) _NOEXCEPT
377ead6f169SHoward Hinnant        : __m_(__u.__m_),
378ead6f169SHoward Hinnant          __owns_(__u.__owns_)
379ead6f169SHoward Hinnant        {
380ead6f169SHoward Hinnant            __u.__m_ = nullptr;
381ead6f169SHoward Hinnant            __u.__owns_ = false;
382ead6f169SHoward Hinnant        }
383ead6f169SHoward Hinnant
384ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
385d08f0d9cSMarshall Clow    shared_lock& operator=(shared_lock&& __u) _NOEXCEPT
386ead6f169SHoward Hinnant    {
387ead6f169SHoward Hinnant        if (__owns_)
388ead6f169SHoward Hinnant            __m_->unlock_shared();
389ead6f169SHoward Hinnant        __m_ = nullptr;
390ead6f169SHoward Hinnant        __owns_ = false;
391ead6f169SHoward Hinnant        __m_ = __u.__m_;
392ead6f169SHoward Hinnant        __owns_ = __u.__owns_;
393ead6f169SHoward Hinnant        __u.__m_ = nullptr;
394ead6f169SHoward Hinnant        __u.__owns_ = false;
395ead6f169SHoward Hinnant        return *this;
396ead6f169SHoward Hinnant    }
397ead6f169SHoward Hinnant
398ead6f169SHoward Hinnant    void lock();
399ead6f169SHoward Hinnant    bool try_lock();
400ead6f169SHoward Hinnant    template <class Rep, class Period>
401ead6f169SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
402ead6f169SHoward Hinnant    template <class Clock, class Duration>
403ead6f169SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
404ead6f169SHoward Hinnant    void unlock();
405ead6f169SHoward Hinnant
406ead6f169SHoward Hinnant    // Setters
407ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
408d08f0d9cSMarshall Clow    void swap(shared_lock& __u) _NOEXCEPT
409ead6f169SHoward Hinnant    {
410ead6f169SHoward Hinnant        _VSTD::swap(__m_, __u.__m_);
411ead6f169SHoward Hinnant        _VSTD::swap(__owns_, __u.__owns_);
412ead6f169SHoward Hinnant    }
413ead6f169SHoward Hinnant
414ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
415d08f0d9cSMarshall Clow    mutex_type* release() _NOEXCEPT
416ead6f169SHoward Hinnant    {
417ead6f169SHoward Hinnant        mutex_type* __m = __m_;
418ead6f169SHoward Hinnant        __m_ = nullptr;
419ead6f169SHoward Hinnant        __owns_ = false;
420ead6f169SHoward Hinnant        return __m;
421ead6f169SHoward Hinnant    }
422ead6f169SHoward Hinnant
423ead6f169SHoward Hinnant    // Getters
424ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
425d08f0d9cSMarshall Clow    bool owns_lock() const _NOEXCEPT {return __owns_;}
426ead6f169SHoward Hinnant
427ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
428d08f0d9cSMarshall Clow    explicit operator bool () const _NOEXCEPT {return __owns_;}
429ead6f169SHoward Hinnant
430ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
431d08f0d9cSMarshall Clow    mutex_type* mutex() const _NOEXCEPT {return __m_;}
432ead6f169SHoward Hinnant};
433ead6f169SHoward Hinnant
434ead6f169SHoward Hinnanttemplate <class _Mutex>
435ead6f169SHoward Hinnantvoid
436ead6f169SHoward Hinnantshared_lock<_Mutex>::lock()
437ead6f169SHoward Hinnant{
438ead6f169SHoward Hinnant    if (__m_ == nullptr)
439ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
440ead6f169SHoward Hinnant    if (__owns_)
441ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
442ead6f169SHoward Hinnant    __m_->lock_shared();
443ead6f169SHoward Hinnant    __owns_ = true;
444ead6f169SHoward Hinnant}
445ead6f169SHoward Hinnant
446ead6f169SHoward Hinnanttemplate <class _Mutex>
447ead6f169SHoward Hinnantbool
448ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock()
449ead6f169SHoward Hinnant{
450ead6f169SHoward Hinnant    if (__m_ == nullptr)
451ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
452ead6f169SHoward Hinnant    if (__owns_)
453ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
454ead6f169SHoward Hinnant    __owns_ = __m_->try_lock_shared();
455ead6f169SHoward Hinnant    return __owns_;
456ead6f169SHoward Hinnant}
457ead6f169SHoward Hinnant
458ead6f169SHoward Hinnanttemplate <class _Mutex>
459ead6f169SHoward Hinnanttemplate <class _Rep, class _Period>
460ead6f169SHoward Hinnantbool
461ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
462ead6f169SHoward Hinnant{
463ead6f169SHoward Hinnant    if (__m_ == nullptr)
464ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
465ead6f169SHoward Hinnant    if (__owns_)
466ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
467ead6f169SHoward Hinnant    __owns_ = __m_->try_lock_shared_for(__d);
468ead6f169SHoward Hinnant    return __owns_;
469ead6f169SHoward Hinnant}
470ead6f169SHoward Hinnant
471ead6f169SHoward Hinnanttemplate <class _Mutex>
472ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration>
473ead6f169SHoward Hinnantbool
474ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
475ead6f169SHoward Hinnant{
476ead6f169SHoward Hinnant    if (__m_ == nullptr)
477ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
478ead6f169SHoward Hinnant    if (__owns_)
479ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
480ead6f169SHoward Hinnant    __owns_ = __m_->try_lock_shared_until(__t);
481ead6f169SHoward Hinnant    return __owns_;
482ead6f169SHoward Hinnant}
483ead6f169SHoward Hinnant
484ead6f169SHoward Hinnanttemplate <class _Mutex>
485ead6f169SHoward Hinnantvoid
486ead6f169SHoward Hinnantshared_lock<_Mutex>::unlock()
487ead6f169SHoward Hinnant{
488ead6f169SHoward Hinnant    if (!__owns_)
489ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::unlock: not locked");
490ead6f169SHoward Hinnant    __m_->unlock_shared();
491ead6f169SHoward Hinnant    __owns_ = false;
492ead6f169SHoward Hinnant}
493ead6f169SHoward Hinnant
494ead6f169SHoward Hinnanttemplate <class _Mutex>
495ead6f169SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
496ead6f169SHoward Hinnantvoid
497d08f0d9cSMarshall Clowswap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT
498ead6f169SHoward Hinnant    {__x.swap(__y);}
499ead6f169SHoward Hinnant
500ead6f169SHoward Hinnant_LIBCPP_END_NAMESPACE_STD
501ead6f169SHoward Hinnant
502b3fcc67fSJonathan Roelofs#endif  // !_LIBCPP_HAS_NO_THREADS
503b3fcc67fSJonathan Roelofs
504ead6f169SHoward Hinnant#endif  // _LIBCPP_STD_VER > 11
505ead6f169SHoward Hinnant
506a016efb1SEric Fiselier_LIBCPP_POP_MACROS
507a016efb1SEric Fiselier
508ead6f169SHoward Hinnant#endif  // _LIBCPP_SHARED_MUTEX
509