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>
127ead6f169SHoward Hinnant
128a016efb1SEric Fiselier_LIBCPP_PUSH_MACROS
129a016efb1SEric Fiselier#include <__undef_macros>
130a016efb1SEric Fiselier
131a016efb1SEric Fiselier
132*c8e84ff2SLouis Dionne#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_LIBRARY)
133ead6f169SHoward Hinnant
134ead6f169SHoward Hinnant#include <__mutex_base>
135ead6f169SHoward Hinnant
136ead6f169SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
137ead6f169SHoward Hinnant#pragma GCC system_header
138ead6f169SHoward Hinnant#endif
139ead6f169SHoward Hinnant
140b3fcc67fSJonathan Roelofs#ifdef _LIBCPP_HAS_NO_THREADS
141b3fcc67fSJonathan Roelofs#error <shared_mutex> is not supported on this single threaded system
142b3fcc67fSJonathan Roelofs#else // !_LIBCPP_HAS_NO_THREADS
143b3fcc67fSJonathan Roelofs
144ead6f169SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD
145ead6f169SHoward Hinnant
146e9c66ad9SMehdi Aministruct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX __shared_mutex_base
147ead6f169SHoward Hinnant{
148ead6f169SHoward Hinnant    mutex               __mut_;
149ead6f169SHoward Hinnant    condition_variable  __gate1_;
150ead6f169SHoward Hinnant    condition_variable  __gate2_;
151ead6f169SHoward Hinnant    unsigned            __state_;
152ead6f169SHoward Hinnant
153ead6f169SHoward Hinnant    static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
154ead6f169SHoward Hinnant    static const unsigned __n_readers_ = ~__write_entered_;
155f69ae471SMarshall Clow
156f69ae471SMarshall Clow    __shared_mutex_base();
157f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default;
158f69ae471SMarshall Clow
159f69ae471SMarshall Clow    __shared_mutex_base(const __shared_mutex_base&) = delete;
160f69ae471SMarshall Clow    __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;
161f69ae471SMarshall Clow
162f69ae471SMarshall Clow    // Exclusive ownership
163f69ae471SMarshall Clow    void lock(); // blocking
164f69ae471SMarshall Clow    bool try_lock();
165f69ae471SMarshall Clow    void unlock();
166f69ae471SMarshall Clow
167f69ae471SMarshall Clow    // Shared ownership
168f69ae471SMarshall Clow    void lock_shared(); // blocking
169f69ae471SMarshall Clow    bool try_lock_shared();
170f69ae471SMarshall Clow    void unlock_shared();
171f69ae471SMarshall Clow
172f69ae471SMarshall Clow//     typedef implementation-defined native_handle_type; // See 30.2.3
173f69ae471SMarshall Clow//     native_handle_type native_handle(); // See 30.2.3
174f69ae471SMarshall Clow};
175f69ae471SMarshall Clow
176f69ae471SMarshall Clow
177f69ae471SMarshall Clow#if _LIBCPP_STD_VER > 14
178e9c66ad9SMehdi Aminiclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex
179f69ae471SMarshall Clow{
180f69ae471SMarshall Clow    __shared_mutex_base __base;
181f69ae471SMarshall Clowpublic:
182ef407482SEric Fiselier    _LIBCPP_INLINE_VISIBILITY shared_mutex() : __base() {}
183f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
184f69ae471SMarshall Clow
185f69ae471SMarshall Clow    shared_mutex(const shared_mutex&) = delete;
186f69ae471SMarshall Clow    shared_mutex& operator=(const shared_mutex&) = delete;
187f69ae471SMarshall Clow
188f69ae471SMarshall Clow    // Exclusive ownership
189f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY void lock()     { return __base.lock(); }
190f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }
191f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY void unlock()   { return __base.unlock(); }
192f69ae471SMarshall Clow
193f69ae471SMarshall Clow    // Shared ownership
194f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY void lock_shared()     { return __base.lock_shared(); }
195f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }
196f69ae471SMarshall Clow    _LIBCPP_INLINE_VISIBILITY void unlock_shared()   { return __base.unlock_shared(); }
197f69ae471SMarshall Clow
198f69ae471SMarshall Clow//     typedef __shared_mutex_base::native_handle_type native_handle_type;
199f69ae471SMarshall Clow//     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); }
200f69ae471SMarshall Clow};
201f69ae471SMarshall Clow#endif
202f69ae471SMarshall Clow
203f69ae471SMarshall Clow
204e9c66ad9SMehdi Aminiclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_timed_mutex
205f69ae471SMarshall Clow{
206f69ae471SMarshall Clow    __shared_mutex_base __base;
207ead6f169SHoward Hinnantpublic:
2087ec93f9bSDavid Majnemer    shared_timed_mutex();
2097ec93f9bSDavid Majnemer    _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;
210ead6f169SHoward Hinnant
2117ec93f9bSDavid Majnemer    shared_timed_mutex(const shared_timed_mutex&) = delete;
2127ec93f9bSDavid Majnemer    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
213ead6f169SHoward Hinnant
214ead6f169SHoward Hinnant    // Exclusive ownership
215ead6f169SHoward Hinnant    void lock();
216ead6f169SHoward Hinnant    bool try_lock();
217ead6f169SHoward Hinnant    template <class _Rep, class _Period>
218ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
219ead6f169SHoward Hinnant        bool
220ead6f169SHoward Hinnant        try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
221ead6f169SHoward Hinnant        {
222ead6f169SHoward Hinnant            return try_lock_until(chrono::steady_clock::now() + __rel_time);
223ead6f169SHoward Hinnant        }
224ead6f169SHoward Hinnant    template <class _Clock, class _Duration>
225bda3c7dfSShoaib Meenai        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
226ead6f169SHoward Hinnant        bool
227ead6f169SHoward Hinnant        try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
228ead6f169SHoward Hinnant    void unlock();
229ead6f169SHoward Hinnant
230ead6f169SHoward Hinnant    // Shared ownership
231ead6f169SHoward Hinnant    void lock_shared();
232ead6f169SHoward Hinnant    bool try_lock_shared();
233ead6f169SHoward Hinnant    template <class _Rep, class _Period>
234ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
235ead6f169SHoward Hinnant        bool
236ead6f169SHoward Hinnant        try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
237ead6f169SHoward Hinnant        {
238ead6f169SHoward Hinnant            return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
239ead6f169SHoward Hinnant        }
240ead6f169SHoward Hinnant    template <class _Clock, class _Duration>
241bda3c7dfSShoaib Meenai        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
242ead6f169SHoward Hinnant        bool
243ead6f169SHoward Hinnant        try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
244ead6f169SHoward Hinnant    void unlock_shared();
245ead6f169SHoward Hinnant};
246ead6f169SHoward Hinnant
247ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration>
248ead6f169SHoward Hinnantbool
2497ec93f9bSDavid Majnemershared_timed_mutex::try_lock_until(
250ead6f169SHoward Hinnant                        const chrono::time_point<_Clock, _Duration>& __abs_time)
251ead6f169SHoward Hinnant{
252f69ae471SMarshall Clow    unique_lock<mutex> __lk(__base.__mut_);
253f69ae471SMarshall Clow    if (__base.__state_ & __base.__write_entered_)
254ead6f169SHoward Hinnant    {
255ead6f169SHoward Hinnant        while (true)
256ead6f169SHoward Hinnant        {
257f69ae471SMarshall Clow            cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time);
258f69ae471SMarshall Clow            if ((__base.__state_ & __base.__write_entered_) == 0)
259ead6f169SHoward Hinnant                break;
260ead6f169SHoward Hinnant            if (__status == cv_status::timeout)
261ead6f169SHoward Hinnant                return false;
262ead6f169SHoward Hinnant        }
263ead6f169SHoward Hinnant    }
264f69ae471SMarshall Clow    __base.__state_ |= __base.__write_entered_;
265f69ae471SMarshall Clow    if (__base.__state_ & __base.__n_readers_)
266ead6f169SHoward Hinnant    {
267ead6f169SHoward Hinnant        while (true)
268ead6f169SHoward Hinnant        {
269f69ae471SMarshall Clow            cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time);
270f69ae471SMarshall Clow            if ((__base.__state_ & __base.__n_readers_) == 0)
271ead6f169SHoward Hinnant                break;
272ead6f169SHoward Hinnant            if (__status == cv_status::timeout)
273ead6f169SHoward Hinnant            {
274f69ae471SMarshall Clow                __base.__state_ &= ~__base.__write_entered_;
275f69ae471SMarshall Clow                __base.__gate1_.notify_all();
276ead6f169SHoward Hinnant                return false;
277ead6f169SHoward Hinnant            }
278ead6f169SHoward Hinnant        }
279ead6f169SHoward Hinnant    }
280ead6f169SHoward Hinnant    return true;
281ead6f169SHoward Hinnant}
282ead6f169SHoward Hinnant
283ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration>
284ead6f169SHoward Hinnantbool
2857ec93f9bSDavid Majnemershared_timed_mutex::try_lock_shared_until(
286ead6f169SHoward Hinnant                        const chrono::time_point<_Clock, _Duration>& __abs_time)
287ead6f169SHoward Hinnant{
288f69ae471SMarshall Clow    unique_lock<mutex> __lk(__base.__mut_);
289f69ae471SMarshall Clow    if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_)
290ead6f169SHoward Hinnant    {
291ead6f169SHoward Hinnant        while (true)
292ead6f169SHoward Hinnant        {
293f69ae471SMarshall Clow            cv_status status = __base.__gate1_.wait_until(__lk, __abs_time);
294f69ae471SMarshall Clow            if ((__base.__state_ & __base.__write_entered_) == 0 &&
295f69ae471SMarshall Clow                                       (__base.__state_ & __base.__n_readers_) < __base.__n_readers_)
296ead6f169SHoward Hinnant                break;
297ead6f169SHoward Hinnant            if (status == cv_status::timeout)
298ead6f169SHoward Hinnant                return false;
299ead6f169SHoward Hinnant        }
300ead6f169SHoward Hinnant    }
301f69ae471SMarshall Clow    unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1;
302f69ae471SMarshall Clow    __base.__state_ &= ~__base.__n_readers_;
303f69ae471SMarshall Clow    __base.__state_ |= __num_readers;
304ead6f169SHoward Hinnant    return true;
305ead6f169SHoward Hinnant}
306ead6f169SHoward Hinnant
307ead6f169SHoward Hinnanttemplate <class _Mutex>
308ead6f169SHoward Hinnantclass shared_lock
309ead6f169SHoward Hinnant{
310ead6f169SHoward Hinnantpublic:
311ead6f169SHoward Hinnant    typedef _Mutex mutex_type;
312ead6f169SHoward Hinnant
313ead6f169SHoward Hinnantprivate:
314ead6f169SHoward Hinnant    mutex_type* __m_;
315ead6f169SHoward Hinnant    bool __owns_;
316ead6f169SHoward Hinnant
317ead6f169SHoward Hinnantpublic:
318ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
319d08f0d9cSMarshall Clow    shared_lock() _NOEXCEPT
320ead6f169SHoward Hinnant        : __m_(nullptr),
321ead6f169SHoward Hinnant          __owns_(false)
322ead6f169SHoward Hinnant        {}
323ead6f169SHoward Hinnant
324ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
325ead6f169SHoward Hinnant    explicit shared_lock(mutex_type& __m)
3263126c881SMarshall Clow        : __m_(_VSTD::addressof(__m)),
327ead6f169SHoward Hinnant          __owns_(true)
328ead6f169SHoward Hinnant        {__m_->lock_shared();}
329ead6f169SHoward Hinnant
330ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
331d08f0d9cSMarshall Clow    shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
3323126c881SMarshall Clow        : __m_(_VSTD::addressof(__m)),
333ead6f169SHoward Hinnant          __owns_(false)
334ead6f169SHoward Hinnant        {}
335ead6f169SHoward Hinnant
336ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
337ead6f169SHoward Hinnant    shared_lock(mutex_type& __m, try_to_lock_t)
3383126c881SMarshall Clow        : __m_(_VSTD::addressof(__m)),
339ead6f169SHoward Hinnant          __owns_(__m.try_lock_shared())
340ead6f169SHoward Hinnant        {}
341ead6f169SHoward Hinnant
342ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
343ead6f169SHoward Hinnant    shared_lock(mutex_type& __m, adopt_lock_t)
3443126c881SMarshall Clow        : __m_(_VSTD::addressof(__m)),
345ead6f169SHoward Hinnant          __owns_(true)
346ead6f169SHoward Hinnant        {}
347ead6f169SHoward Hinnant
348ead6f169SHoward Hinnant    template <class _Clock, class _Duration>
349ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
350ead6f169SHoward Hinnant        shared_lock(mutex_type& __m,
351ead6f169SHoward Hinnant                    const chrono::time_point<_Clock, _Duration>& __abs_time)
3523126c881SMarshall Clow            : __m_(_VSTD::addressof(__m)),
353ead6f169SHoward Hinnant              __owns_(__m.try_lock_shared_until(__abs_time))
354ead6f169SHoward Hinnant            {}
355ead6f169SHoward Hinnant
356ead6f169SHoward Hinnant    template <class _Rep, class _Period>
357ead6f169SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
358ead6f169SHoward Hinnant        shared_lock(mutex_type& __m,
359ead6f169SHoward Hinnant                    const chrono::duration<_Rep, _Period>& __rel_time)
3603126c881SMarshall Clow            : __m_(_VSTD::addressof(__m)),
361ead6f169SHoward Hinnant              __owns_(__m.try_lock_shared_for(__rel_time))
362ead6f169SHoward Hinnant            {}
363ead6f169SHoward Hinnant
364ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
365ead6f169SHoward Hinnant    ~shared_lock()
366ead6f169SHoward Hinnant    {
367ead6f169SHoward Hinnant        if (__owns_)
368ead6f169SHoward Hinnant            __m_->unlock_shared();
369ead6f169SHoward Hinnant    }
370ead6f169SHoward Hinnant
371ead6f169SHoward Hinnant    shared_lock(shared_lock const&) = delete;
372ead6f169SHoward Hinnant    shared_lock& operator=(shared_lock const&) = delete;
373ead6f169SHoward Hinnant
374ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
375d08f0d9cSMarshall Clow    shared_lock(shared_lock&& __u) _NOEXCEPT
376ead6f169SHoward Hinnant        : __m_(__u.__m_),
377ead6f169SHoward Hinnant          __owns_(__u.__owns_)
378ead6f169SHoward Hinnant        {
379ead6f169SHoward Hinnant            __u.__m_ = nullptr;
380ead6f169SHoward Hinnant            __u.__owns_ = false;
381ead6f169SHoward Hinnant        }
382ead6f169SHoward Hinnant
383ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
384d08f0d9cSMarshall Clow    shared_lock& operator=(shared_lock&& __u) _NOEXCEPT
385ead6f169SHoward Hinnant    {
386ead6f169SHoward Hinnant        if (__owns_)
387ead6f169SHoward Hinnant            __m_->unlock_shared();
388ead6f169SHoward Hinnant        __m_ = nullptr;
389ead6f169SHoward Hinnant        __owns_ = false;
390ead6f169SHoward Hinnant        __m_ = __u.__m_;
391ead6f169SHoward Hinnant        __owns_ = __u.__owns_;
392ead6f169SHoward Hinnant        __u.__m_ = nullptr;
393ead6f169SHoward Hinnant        __u.__owns_ = false;
394ead6f169SHoward Hinnant        return *this;
395ead6f169SHoward Hinnant    }
396ead6f169SHoward Hinnant
397ead6f169SHoward Hinnant    void lock();
398ead6f169SHoward Hinnant    bool try_lock();
399ead6f169SHoward Hinnant    template <class Rep, class Period>
400ead6f169SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
401ead6f169SHoward Hinnant    template <class Clock, class Duration>
402ead6f169SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
403ead6f169SHoward Hinnant    void unlock();
404ead6f169SHoward Hinnant
405ead6f169SHoward Hinnant    // Setters
406ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
407d08f0d9cSMarshall Clow    void swap(shared_lock& __u) _NOEXCEPT
408ead6f169SHoward Hinnant    {
409ead6f169SHoward Hinnant        _VSTD::swap(__m_, __u.__m_);
410ead6f169SHoward Hinnant        _VSTD::swap(__owns_, __u.__owns_);
411ead6f169SHoward Hinnant    }
412ead6f169SHoward Hinnant
413ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
414d08f0d9cSMarshall Clow    mutex_type* release() _NOEXCEPT
415ead6f169SHoward Hinnant    {
416ead6f169SHoward Hinnant        mutex_type* __m = __m_;
417ead6f169SHoward Hinnant        __m_ = nullptr;
418ead6f169SHoward Hinnant        __owns_ = false;
419ead6f169SHoward Hinnant        return __m;
420ead6f169SHoward Hinnant    }
421ead6f169SHoward Hinnant
422ead6f169SHoward Hinnant    // Getters
423ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
424d08f0d9cSMarshall Clow    bool owns_lock() const _NOEXCEPT {return __owns_;}
425ead6f169SHoward Hinnant
426ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
427d08f0d9cSMarshall Clow    explicit operator bool () const _NOEXCEPT {return __owns_;}
428ead6f169SHoward Hinnant
429ead6f169SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
430d08f0d9cSMarshall Clow    mutex_type* mutex() const _NOEXCEPT {return __m_;}
431ead6f169SHoward Hinnant};
432ead6f169SHoward Hinnant
433ead6f169SHoward Hinnanttemplate <class _Mutex>
434ead6f169SHoward Hinnantvoid
435ead6f169SHoward Hinnantshared_lock<_Mutex>::lock()
436ead6f169SHoward Hinnant{
437ead6f169SHoward Hinnant    if (__m_ == nullptr)
438ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
439ead6f169SHoward Hinnant    if (__owns_)
440ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
441ead6f169SHoward Hinnant    __m_->lock_shared();
442ead6f169SHoward Hinnant    __owns_ = true;
443ead6f169SHoward Hinnant}
444ead6f169SHoward Hinnant
445ead6f169SHoward Hinnanttemplate <class _Mutex>
446ead6f169SHoward Hinnantbool
447ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock()
448ead6f169SHoward Hinnant{
449ead6f169SHoward Hinnant    if (__m_ == nullptr)
450ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
451ead6f169SHoward Hinnant    if (__owns_)
452ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
453ead6f169SHoward Hinnant    __owns_ = __m_->try_lock_shared();
454ead6f169SHoward Hinnant    return __owns_;
455ead6f169SHoward Hinnant}
456ead6f169SHoward Hinnant
457ead6f169SHoward Hinnanttemplate <class _Mutex>
458ead6f169SHoward Hinnanttemplate <class _Rep, class _Period>
459ead6f169SHoward Hinnantbool
460ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
461ead6f169SHoward Hinnant{
462ead6f169SHoward Hinnant    if (__m_ == nullptr)
463ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
464ead6f169SHoward Hinnant    if (__owns_)
465ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
466ead6f169SHoward Hinnant    __owns_ = __m_->try_lock_shared_for(__d);
467ead6f169SHoward Hinnant    return __owns_;
468ead6f169SHoward Hinnant}
469ead6f169SHoward Hinnant
470ead6f169SHoward Hinnanttemplate <class _Mutex>
471ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration>
472ead6f169SHoward Hinnantbool
473ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
474ead6f169SHoward Hinnant{
475ead6f169SHoward Hinnant    if (__m_ == nullptr)
476ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
477ead6f169SHoward Hinnant    if (__owns_)
478ead6f169SHoward Hinnant        __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
479ead6f169SHoward Hinnant    __owns_ = __m_->try_lock_shared_until(__t);
480ead6f169SHoward Hinnant    return __owns_;
481ead6f169SHoward Hinnant}
482ead6f169SHoward Hinnant
483ead6f169SHoward Hinnanttemplate <class _Mutex>
484ead6f169SHoward Hinnantvoid
485ead6f169SHoward Hinnantshared_lock<_Mutex>::unlock()
486ead6f169SHoward Hinnant{
487ead6f169SHoward Hinnant    if (!__owns_)
488ead6f169SHoward Hinnant        __throw_system_error(EPERM, "shared_lock::unlock: not locked");
489ead6f169SHoward Hinnant    __m_->unlock_shared();
490ead6f169SHoward Hinnant    __owns_ = false;
491ead6f169SHoward Hinnant}
492ead6f169SHoward Hinnant
493ead6f169SHoward Hinnanttemplate <class _Mutex>
494ead6f169SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
495ead6f169SHoward Hinnantvoid
496d08f0d9cSMarshall Clowswap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT
497ead6f169SHoward Hinnant    {__x.swap(__y);}
498ead6f169SHoward Hinnant
499ead6f169SHoward Hinnant_LIBCPP_END_NAMESPACE_STD
500ead6f169SHoward Hinnant
501b3fcc67fSJonathan Roelofs#endif  // !_LIBCPP_HAS_NO_THREADS
502b3fcc67fSJonathan Roelofs
503ead6f169SHoward Hinnant#endif  // _LIBCPP_STD_VER > 11
504ead6f169SHoward Hinnant
505a016efb1SEric Fiselier_LIBCPP_POP_MACROS
506a016efb1SEric Fiselier
507ead6f169SHoward Hinnant#endif  // _LIBCPP_SHARED_MUTEX
508