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