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