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
227ec93f9bSDavid Majnemerclass shared_timed_mutex
23ead6f169SHoward Hinnant{
24ead6f169SHoward Hinnantpublic:
257ec93f9bSDavid Majnemer    shared_timed_mutex();
267ec93f9bSDavid Majnemer    ~shared_timed_mutex();
27ead6f169SHoward Hinnant
287ec93f9bSDavid Majnemer    shared_timed_mutex(const shared_timed_mutex&) = delete;
297ec93f9bSDavid Majnemer    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
30ead6f169SHoward Hinnant
31ead6f169SHoward Hinnant    // Exclusive ownership
32ead6f169SHoward Hinnant    void lock(); // blocking
33ead6f169SHoward Hinnant    bool try_lock();
34ead6f169SHoward Hinnant    template <class Rep, class Period>
35ead6f169SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
36ead6f169SHoward Hinnant    template <class Clock, class Duration>
37ead6f169SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
38ead6f169SHoward Hinnant    void unlock();
39ead6f169SHoward Hinnant
40ead6f169SHoward Hinnant    // Shared ownership
41ead6f169SHoward Hinnant    void lock_shared(); // blocking
42ead6f169SHoward Hinnant    bool try_lock_shared();
43ead6f169SHoward Hinnant    template <class Rep, class Period>
44ead6f169SHoward Hinnant        bool
45ead6f169SHoward Hinnant        try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
46ead6f169SHoward Hinnant    template <class Clock, class Duration>
47ead6f169SHoward Hinnant        bool
48ead6f169SHoward Hinnant        try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
49ead6f169SHoward Hinnant    void unlock_shared();
50ead6f169SHoward Hinnant};
51ead6f169SHoward Hinnant
52ead6f169SHoward Hinnanttemplate <class Mutex>
53ead6f169SHoward Hinnantclass shared_lock
54ead6f169SHoward Hinnant{
55ead6f169SHoward Hinnantpublic:
56ead6f169SHoward Hinnant    typedef Mutex mutex_type;
57ead6f169SHoward Hinnant
58ead6f169SHoward Hinnant    // Shared locking
59ead6f169SHoward Hinnant    shared_lock() noexcept;
60ead6f169SHoward Hinnant    explicit shared_lock(mutex_type& m); // blocking
61ead6f169SHoward Hinnant    shared_lock(mutex_type& m, defer_lock_t) noexcept;
62ead6f169SHoward Hinnant    shared_lock(mutex_type& m, try_to_lock_t);
63ead6f169SHoward Hinnant    shared_lock(mutex_type& m, adopt_lock_t);
64ead6f169SHoward Hinnant    template <class Clock, class Duration>
65ead6f169SHoward Hinnant        shared_lock(mutex_type& m,
66ead6f169SHoward Hinnant                    const chrono::time_point<Clock, Duration>& abs_time);
67ead6f169SHoward Hinnant    template <class Rep, class Period>
68ead6f169SHoward Hinnant        shared_lock(mutex_type& m,
69ead6f169SHoward Hinnant                    const chrono::duration<Rep, Period>& rel_time);
70ead6f169SHoward Hinnant    ~shared_lock();
71ead6f169SHoward Hinnant
72ead6f169SHoward Hinnant    shared_lock(shared_lock const&) = delete;
73ead6f169SHoward Hinnant    shared_lock& operator=(shared_lock const&) = delete;
74ead6f169SHoward Hinnant
75ead6f169SHoward Hinnant    shared_lock(shared_lock&& u) noexcept;
76ead6f169SHoward Hinnant    shared_lock& operator=(shared_lock&& u) noexcept;
77ead6f169SHoward Hinnant
78ead6f169SHoward Hinnant    void lock(); // blocking
79ead6f169SHoward Hinnant    bool try_lock();
80ead6f169SHoward Hinnant    template <class Rep, class Period>
81ead6f169SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
82ead6f169SHoward Hinnant    template <class Clock, class Duration>
83ead6f169SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
84ead6f169SHoward Hinnant    void unlock();
85ead6f169SHoward Hinnant
86ead6f169SHoward Hinnant    // Setters
87ead6f169SHoward Hinnant    void swap(shared_lock& u) noexcept;
88ead6f169SHoward Hinnant    mutex_type* release() noexcept;
89ead6f169SHoward Hinnant
90ead6f169SHoward Hinnant    // Getters
91ead6f169SHoward Hinnant    bool owns_lock() const noexcept;
92ead6f169SHoward Hinnant    explicit operator bool () const noexcept;
93ead6f169SHoward Hinnant    mutex_type* mutex() const noexcept;
94ead6f169SHoward Hinnant};
95ead6f169SHoward Hinnant
96ead6f169SHoward Hinnanttemplate <class Mutex>
97ead6f169SHoward Hinnant    void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
98ead6f169SHoward Hinnant
99ead6f169SHoward Hinnant}  // std
100ead6f169SHoward Hinnant
101ead6f169SHoward Hinnant*/
102ead6f169SHoward Hinnant
103ead6f169SHoward Hinnant#include <__config>
104ead6f169SHoward Hinnant
105ead6f169SHoward Hinnant#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_SHARED_MUTEX)
106ead6f169SHoward Hinnant
107ead6f169SHoward Hinnant#include <__mutex_base>
108ead6f169SHoward Hinnant
109ead6f169SHoward Hinnant#include <__undef_min_max>
110ead6f169SHoward Hinnant
111ead6f169SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
112ead6f169SHoward Hinnant#pragma GCC system_header
113ead6f169SHoward Hinnant#endif
114ead6f169SHoward Hinnant
115*b3fcc67fSJonathan Roelofs#ifdef _LIBCPP_HAS_NO_THREADS
116*b3fcc67fSJonathan Roelofs#error <shared_mutex> is not supported on this single threaded system
117*b3fcc67fSJonathan Roelofs#else // !_LIBCPP_HAS_NO_THREADS
118*b3fcc67fSJonathan Roelofs
119ead6f169SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD
120ead6f169SHoward Hinnant
1217ec93f9bSDavid Majnemerclass _LIBCPP_TYPE_VIS shared_timed_mutex
122ead6f169SHoward Hinnant{
123ead6f169SHoward Hinnant    mutex               __mut_;
124ead6f169SHoward Hinnant    condition_variable  __gate1_;
125ead6f169SHoward Hinnant    condition_variable  __gate2_;
126ead6f169SHoward Hinnant    unsigned            __state_;
127ead6f169SHoward Hinnant
128ead6f169SHoward Hinnant    static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
129ead6f169SHoward Hinnant    static const unsigned __n_readers_ = ~__write_entered_;
130ead6f169SHoward Hinnantpublic:
1317ec93f9bSDavid Majnemer    shared_timed_mutex();
1327ec93f9bSDavid Majnemer    _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;
133ead6f169SHoward Hinnant
1347ec93f9bSDavid Majnemer    shared_timed_mutex(const shared_timed_mutex&) = delete;
1357ec93f9bSDavid Majnemer    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
136ead6f169SHoward Hinnant
137ead6f169SHoward Hinnant    // Exclusive ownership
138ead6f169SHoward Hinnant    void lock();
139ead6f169SHoward Hinnant    bool try_lock();
140ead6f169SHoward Hinnant    template <class _Rep, class _Period>
141ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
142ead6f169SHoward Hinnant        bool
143ead6f169SHoward Hinnant        try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
144ead6f169SHoward Hinnant        {
145ead6f169SHoward Hinnant            return try_lock_until(chrono::steady_clock::now() + __rel_time);
146ead6f169SHoward Hinnant        }
147ead6f169SHoward Hinnant    template <class _Clock, class _Duration>
148ead6f169SHoward Hinnant        bool
149ead6f169SHoward Hinnant        try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
150ead6f169SHoward Hinnant    void unlock();
151ead6f169SHoward Hinnant
152ead6f169SHoward Hinnant    // Shared ownership
153ead6f169SHoward Hinnant    void lock_shared();
154ead6f169SHoward Hinnant    bool try_lock_shared();
155ead6f169SHoward Hinnant    template <class _Rep, class _Period>
156ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
157ead6f169SHoward Hinnant        bool
158ead6f169SHoward Hinnant        try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
159ead6f169SHoward Hinnant        {
160ead6f169SHoward Hinnant            return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
161ead6f169SHoward Hinnant        }
162ead6f169SHoward Hinnant    template <class _Clock, class _Duration>
163ead6f169SHoward Hinnant        bool
164ead6f169SHoward Hinnant        try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
165ead6f169SHoward Hinnant    void unlock_shared();
166ead6f169SHoward Hinnant};
167ead6f169SHoward Hinnant
168ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration>
169ead6f169SHoward Hinnantbool
1707ec93f9bSDavid Majnemershared_timed_mutex::try_lock_until(
171ead6f169SHoward Hinnant                        const chrono::time_point<_Clock, _Duration>& __abs_time)
172ead6f169SHoward Hinnant{
173ead6f169SHoward Hinnant    unique_lock<mutex> __lk(__mut_);
174ead6f169SHoward Hinnant    if (__state_ & __write_entered_)
175ead6f169SHoward Hinnant    {
176ead6f169SHoward Hinnant        while (true)
177ead6f169SHoward Hinnant        {
178ead6f169SHoward Hinnant            cv_status __status = __gate1_.wait_until(__lk, __abs_time);
179ead6f169SHoward Hinnant            if ((__state_ & __write_entered_) == 0)
180ead6f169SHoward Hinnant                break;
181ead6f169SHoward Hinnant            if (__status == cv_status::timeout)
182ead6f169SHoward Hinnant                return false;
183ead6f169SHoward Hinnant        }
184ead6f169SHoward Hinnant    }
185ead6f169SHoward Hinnant    __state_ |= __write_entered_;
186ead6f169SHoward Hinnant    if (__state_ & __n_readers_)
187ead6f169SHoward Hinnant    {
188ead6f169SHoward Hinnant        while (true)
189ead6f169SHoward Hinnant        {
190ead6f169SHoward Hinnant            cv_status __status = __gate2_.wait_until(__lk, __abs_time);
191ead6f169SHoward Hinnant            if ((__state_ & __n_readers_) == 0)
192ead6f169SHoward Hinnant                break;
193ead6f169SHoward Hinnant            if (__status == cv_status::timeout)
194ead6f169SHoward Hinnant            {
195ead6f169SHoward Hinnant                __state_ &= ~__write_entered_;
196ead6f169SHoward Hinnant                return false;
197ead6f169SHoward Hinnant            }
198ead6f169SHoward Hinnant        }
199ead6f169SHoward Hinnant    }
200ead6f169SHoward Hinnant    return true;
201ead6f169SHoward Hinnant}
202ead6f169SHoward Hinnant
203ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration>
204ead6f169SHoward Hinnantbool
2057ec93f9bSDavid Majnemershared_timed_mutex::try_lock_shared_until(
206ead6f169SHoward Hinnant                        const chrono::time_point<_Clock, _Duration>& __abs_time)
207ead6f169SHoward Hinnant{
208ead6f169SHoward Hinnant    unique_lock<mutex> __lk(__mut_);
209ead6f169SHoward Hinnant    if ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
210ead6f169SHoward Hinnant    {
211ead6f169SHoward Hinnant        while (true)
212ead6f169SHoward Hinnant        {
213ead6f169SHoward Hinnant            cv_status status = __gate1_.wait_until(__lk, __abs_time);
214ead6f169SHoward Hinnant            if ((__state_ & __write_entered_) == 0 &&
215ead6f169SHoward Hinnant                                       (__state_ & __n_readers_) < __n_readers_)
216ead6f169SHoward Hinnant                break;
217ead6f169SHoward Hinnant            if (status == cv_status::timeout)
218ead6f169SHoward Hinnant                return false;
219ead6f169SHoward Hinnant        }
220ead6f169SHoward Hinnant    }
221ead6f169SHoward Hinnant    unsigned __num_readers = (__state_ & __n_readers_) + 1;
222ead6f169SHoward Hinnant    __state_ &= ~__n_readers_;
223ead6f169SHoward Hinnant    __state_ |= __num_readers;
224ead6f169SHoward Hinnant    return true;
225ead6f169SHoward Hinnant}
226ead6f169SHoward Hinnant
227ead6f169SHoward Hinnanttemplate <class _Mutex>
228ead6f169SHoward Hinnantclass shared_lock
229ead6f169SHoward Hinnant{
230ead6f169SHoward Hinnantpublic:
231ead6f169SHoward Hinnant    typedef _Mutex mutex_type;
232ead6f169SHoward Hinnant
233ead6f169SHoward Hinnantprivate:
234ead6f169SHoward Hinnant    mutex_type* __m_;
235ead6f169SHoward Hinnant    bool __owns_;
236ead6f169SHoward Hinnant
237ead6f169SHoward Hinnantpublic:
238ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
239d08f0d9cSMarshall Clow    shared_lock() _NOEXCEPT
240ead6f169SHoward Hinnant        : __m_(nullptr),
241ead6f169SHoward Hinnant          __owns_(false)
242ead6f169SHoward Hinnant        {}
243ead6f169SHoward Hinnant
244ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
245ead6f169SHoward Hinnant    explicit shared_lock(mutex_type& __m)
246ead6f169SHoward Hinnant        : __m_(&__m),
247ead6f169SHoward Hinnant          __owns_(true)
248ead6f169SHoward Hinnant        {__m_->lock_shared();}
249ead6f169SHoward Hinnant
250ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
251d08f0d9cSMarshall Clow    shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
252ead6f169SHoward Hinnant        : __m_(&__m),
253ead6f169SHoward Hinnant          __owns_(false)
254ead6f169SHoward Hinnant        {}
255ead6f169SHoward Hinnant
256ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
257ead6f169SHoward Hinnant    shared_lock(mutex_type& __m, try_to_lock_t)
258ead6f169SHoward Hinnant        : __m_(&__m),
259ead6f169SHoward Hinnant          __owns_(__m.try_lock_shared())
260ead6f169SHoward Hinnant        {}
261ead6f169SHoward Hinnant
262ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
263ead6f169SHoward Hinnant    shared_lock(mutex_type& __m, adopt_lock_t)
264ead6f169SHoward Hinnant        : __m_(&__m),
265ead6f169SHoward Hinnant          __owns_(true)
266ead6f169SHoward Hinnant        {}
267ead6f169SHoward Hinnant
268ead6f169SHoward Hinnant    template <class _Clock, class _Duration>
269ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
270ead6f169SHoward Hinnant        shared_lock(mutex_type& __m,
271ead6f169SHoward Hinnant                    const chrono::time_point<_Clock, _Duration>& __abs_time)
272ead6f169SHoward Hinnant            : __m_(&__m),
273ead6f169SHoward Hinnant              __owns_(__m.try_lock_shared_until(__abs_time))
274ead6f169SHoward Hinnant            {}
275ead6f169SHoward Hinnant
276ead6f169SHoward Hinnant    template <class _Rep, class _Period>
277ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
278ead6f169SHoward Hinnant        shared_lock(mutex_type& __m,
279ead6f169SHoward Hinnant                    const chrono::duration<_Rep, _Period>& __rel_time)
280ead6f169SHoward Hinnant            : __m_(&__m),
281ead6f169SHoward Hinnant              __owns_(__m.try_lock_shared_for(__rel_time))
282ead6f169SHoward Hinnant            {}
283ead6f169SHoward Hinnant
284ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
285ead6f169SHoward Hinnant    ~shared_lock()
286ead6f169SHoward Hinnant    {
287ead6f169SHoward Hinnant        if (__owns_)
288ead6f169SHoward Hinnant            __m_->unlock_shared();
289ead6f169SHoward Hinnant    }
290ead6f169SHoward Hinnant
291ead6f169SHoward Hinnant    shared_lock(shared_lock const&) = delete;
292ead6f169SHoward Hinnant    shared_lock& operator=(shared_lock const&) = delete;
293ead6f169SHoward Hinnant
294ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
295d08f0d9cSMarshall Clow    shared_lock(shared_lock&& __u) _NOEXCEPT
296ead6f169SHoward Hinnant        : __m_(__u.__m_),
297ead6f169SHoward Hinnant          __owns_(__u.__owns_)
298ead6f169SHoward Hinnant        {
299ead6f169SHoward Hinnant            __u.__m_ = nullptr;
300ead6f169SHoward Hinnant            __u.__owns_ = false;
301ead6f169SHoward Hinnant        }
302ead6f169SHoward Hinnant
303ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
304d08f0d9cSMarshall Clow    shared_lock& operator=(shared_lock&& __u) _NOEXCEPT
305ead6f169SHoward Hinnant    {
306ead6f169SHoward Hinnant        if (__owns_)
307ead6f169SHoward Hinnant            __m_->unlock_shared();
308ead6f169SHoward Hinnant        __m_ = nullptr;
309ead6f169SHoward Hinnant        __owns_ = false;
310ead6f169SHoward Hinnant        __m_ = __u.__m_;
311ead6f169SHoward Hinnant        __owns_ = __u.__owns_;
312ead6f169SHoward Hinnant        __u.__m_ = nullptr;
313ead6f169SHoward Hinnant        __u.__owns_ = false;
314ead6f169SHoward Hinnant        return *this;
315ead6f169SHoward Hinnant    }
316ead6f169SHoward Hinnant
317ead6f169SHoward Hinnant    void lock();
318ead6f169SHoward Hinnant    bool try_lock();
319ead6f169SHoward Hinnant    template <class Rep, class Period>
320ead6f169SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
321ead6f169SHoward Hinnant    template <class Clock, class Duration>
322ead6f169SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
323ead6f169SHoward Hinnant    void unlock();
324ead6f169SHoward Hinnant
325ead6f169SHoward Hinnant    // Setters
326ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
327d08f0d9cSMarshall Clow    void swap(shared_lock& __u) _NOEXCEPT
328ead6f169SHoward Hinnant    {
329ead6f169SHoward Hinnant        _VSTD::swap(__m_, __u.__m_);
330ead6f169SHoward Hinnant        _VSTD::swap(__owns_, __u.__owns_);
331ead6f169SHoward Hinnant    }
332ead6f169SHoward Hinnant
333ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
334d08f0d9cSMarshall Clow    mutex_type* release() _NOEXCEPT
335ead6f169SHoward Hinnant    {
336ead6f169SHoward Hinnant        mutex_type* __m = __m_;
337ead6f169SHoward Hinnant        __m_ = nullptr;
338ead6f169SHoward Hinnant        __owns_ = false;
339ead6f169SHoward Hinnant        return __m;
340ead6f169SHoward Hinnant    }
341ead6f169SHoward Hinnant
342ead6f169SHoward Hinnant    // Getters
343ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
344d08f0d9cSMarshall Clow    bool owns_lock() const _NOEXCEPT {return __owns_;}
345ead6f169SHoward Hinnant
346ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
347d08f0d9cSMarshall Clow    explicit operator bool () const _NOEXCEPT {return __owns_;}
348ead6f169SHoward Hinnant
349ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
350d08f0d9cSMarshall Clow    mutex_type* mutex() const _NOEXCEPT {return __m_;}
351ead6f169SHoward Hinnant};
352ead6f169SHoward Hinnant
353ead6f169SHoward Hinnanttemplate <class _Mutex>
354ead6f169SHoward Hinnantvoid
355ead6f169SHoward Hinnantshared_lock<_Mutex>::lock()
356ead6f169SHoward Hinnant{
357ead6f169SHoward Hinnant    if (__m_ == nullptr)
358ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
359ead6f169SHoward Hinnant    if (__owns_)
360ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
361ead6f169SHoward Hinnant    __m_->lock_shared();
362ead6f169SHoward Hinnant    __owns_ = true;
363ead6f169SHoward Hinnant}
364ead6f169SHoward Hinnant
365ead6f169SHoward Hinnanttemplate <class _Mutex>
366ead6f169SHoward Hinnantbool
367ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock()
368ead6f169SHoward Hinnant{
369ead6f169SHoward Hinnant    if (__m_ == nullptr)
370ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
371ead6f169SHoward Hinnant    if (__owns_)
372ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
373ead6f169SHoward Hinnant    __owns_ = __m_->try_lock_shared();
374ead6f169SHoward Hinnant    return __owns_;
375ead6f169SHoward Hinnant}
376ead6f169SHoward Hinnant
377ead6f169SHoward Hinnanttemplate <class _Mutex>
378ead6f169SHoward Hinnanttemplate <class _Rep, class _Period>
379ead6f169SHoward Hinnantbool
380ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
381ead6f169SHoward Hinnant{
382ead6f169SHoward Hinnant    if (__m_ == nullptr)
383ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
384ead6f169SHoward Hinnant    if (__owns_)
385ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
386ead6f169SHoward Hinnant    __owns_ = __m_->try_lock_shared_for(__d);
387ead6f169SHoward Hinnant    return __owns_;
388ead6f169SHoward Hinnant}
389ead6f169SHoward Hinnant
390ead6f169SHoward Hinnanttemplate <class _Mutex>
391ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration>
392ead6f169SHoward Hinnantbool
393ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
394ead6f169SHoward Hinnant{
395ead6f169SHoward Hinnant    if (__m_ == nullptr)
396ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
397ead6f169SHoward Hinnant    if (__owns_)
398ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
399ead6f169SHoward Hinnant    __owns_ = __m_->try_lock_shared_until(__t);
400ead6f169SHoward Hinnant    return __owns_;
401ead6f169SHoward Hinnant}
402ead6f169SHoward Hinnant
403ead6f169SHoward Hinnanttemplate <class _Mutex>
404ead6f169SHoward Hinnantvoid
405ead6f169SHoward Hinnantshared_lock<_Mutex>::unlock()
406ead6f169SHoward Hinnant{
407ead6f169SHoward Hinnant    if (!__owns_)
408ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::unlock: not locked");
409ead6f169SHoward Hinnant    __m_->unlock_shared();
410ead6f169SHoward Hinnant    __owns_ = false;
411ead6f169SHoward Hinnant}
412ead6f169SHoward Hinnant
413ead6f169SHoward Hinnanttemplate <class _Mutex>
414ead6f169SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
415ead6f169SHoward Hinnantvoid
416d08f0d9cSMarshall Clowswap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT
417ead6f169SHoward Hinnant    {__x.swap(__y);}
418ead6f169SHoward Hinnant
419ead6f169SHoward Hinnant_LIBCPP_END_NAMESPACE_STD
420ead6f169SHoward Hinnant
421*b3fcc67fSJonathan Roelofs#endif  // !_LIBCPP_HAS_NO_THREADS
422*b3fcc67fSJonathan Roelofs
423ead6f169SHoward Hinnant#endif  // _LIBCPP_STD_VER > 11
424ead6f169SHoward Hinnant
425ead6f169SHoward Hinnant#endif  // _LIBCPP_SHARED_MUTEX
426