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