1e78f53d1SNikolas Klauser// -*- C++ -*- 2e78f53d1SNikolas Klauser//===----------------------------------------------------------------------===// 3e78f53d1SNikolas Klauser// 4e78f53d1SNikolas Klauser// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5e78f53d1SNikolas Klauser// See https://llvm.org/LICENSE.txt for license information. 6e78f53d1SNikolas Klauser// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7e78f53d1SNikolas Klauser// 8e78f53d1SNikolas Klauser//===----------------------------------------------------------------------===// 9e78f53d1SNikolas Klauser 10*ce777190SNikolas Klauser#ifndef _LIBCPP___CXX03_SHARED_MUTEX 11*ce777190SNikolas Klauser#define _LIBCPP___CXX03_SHARED_MUTEX 12e78f53d1SNikolas Klauser 13e78f53d1SNikolas Klauser/* 14e78f53d1SNikolas Klauser shared_mutex synopsis 15e78f53d1SNikolas Klauser 16e78f53d1SNikolas Klauser// C++1y 17e78f53d1SNikolas Klauser 18e78f53d1SNikolas Klausernamespace std 19e78f53d1SNikolas Klauser{ 20e78f53d1SNikolas Klauser 21e78f53d1SNikolas Klauserclass shared_mutex // C++17 22e78f53d1SNikolas Klauser{ 23e78f53d1SNikolas Klauserpublic: 24e78f53d1SNikolas Klauser shared_mutex(); 25e78f53d1SNikolas Klauser ~shared_mutex(); 26e78f53d1SNikolas Klauser 27e78f53d1SNikolas Klauser shared_mutex(const shared_mutex&) = delete; 28e78f53d1SNikolas Klauser shared_mutex& operator=(const shared_mutex&) = delete; 29e78f53d1SNikolas Klauser 30e78f53d1SNikolas Klauser // Exclusive ownership 31e78f53d1SNikolas Klauser void lock(); // blocking 32e78f53d1SNikolas Klauser bool try_lock(); 33e78f53d1SNikolas Klauser void unlock(); 34e78f53d1SNikolas Klauser 35e78f53d1SNikolas Klauser // Shared ownership 36e78f53d1SNikolas Klauser void lock_shared(); // blocking 37e78f53d1SNikolas Klauser bool try_lock_shared(); 38e78f53d1SNikolas Klauser void unlock_shared(); 39e78f53d1SNikolas Klauser 40e78f53d1SNikolas Klauser typedef implementation-defined native_handle_type; // See 30.2.3 41e78f53d1SNikolas Klauser native_handle_type native_handle(); // See 30.2.3 42e78f53d1SNikolas Klauser}; 43e78f53d1SNikolas Klauser 44e78f53d1SNikolas Klauserclass shared_timed_mutex 45e78f53d1SNikolas Klauser{ 46e78f53d1SNikolas Klauserpublic: 47e78f53d1SNikolas Klauser shared_timed_mutex(); 48e78f53d1SNikolas Klauser ~shared_timed_mutex(); 49e78f53d1SNikolas Klauser 50e78f53d1SNikolas Klauser shared_timed_mutex(const shared_timed_mutex&) = delete; 51e78f53d1SNikolas Klauser shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; 52e78f53d1SNikolas Klauser 53e78f53d1SNikolas Klauser // Exclusive ownership 54e78f53d1SNikolas Klauser void lock(); // blocking 55e78f53d1SNikolas Klauser bool try_lock(); 56e78f53d1SNikolas Klauser template <class Rep, class Period> 57e78f53d1SNikolas Klauser bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 58e78f53d1SNikolas Klauser template <class Clock, class Duration> 59e78f53d1SNikolas Klauser bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 60e78f53d1SNikolas Klauser void unlock(); 61e78f53d1SNikolas Klauser 62e78f53d1SNikolas Klauser // Shared ownership 63e78f53d1SNikolas Klauser void lock_shared(); // blocking 64e78f53d1SNikolas Klauser bool try_lock_shared(); 65e78f53d1SNikolas Klauser template <class Rep, class Period> 66e78f53d1SNikolas Klauser bool 67e78f53d1SNikolas Klauser try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time); 68e78f53d1SNikolas Klauser template <class Clock, class Duration> 69e78f53d1SNikolas Klauser bool 70e78f53d1SNikolas Klauser try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time); 71e78f53d1SNikolas Klauser void unlock_shared(); 72e78f53d1SNikolas Klauser}; 73e78f53d1SNikolas Klauser 74e78f53d1SNikolas Klausertemplate <class Mutex> 75e78f53d1SNikolas Klauserclass shared_lock 76e78f53d1SNikolas Klauser{ 77e78f53d1SNikolas Klauserpublic: 78e78f53d1SNikolas Klauser typedef Mutex mutex_type; 79e78f53d1SNikolas Klauser 80e78f53d1SNikolas Klauser // Shared locking 81e78f53d1SNikolas Klauser shared_lock() noexcept; 82e78f53d1SNikolas Klauser explicit shared_lock(mutex_type& m); // blocking 83e78f53d1SNikolas Klauser shared_lock(mutex_type& m, defer_lock_t) noexcept; 84e78f53d1SNikolas Klauser shared_lock(mutex_type& m, try_to_lock_t); 85e78f53d1SNikolas Klauser shared_lock(mutex_type& m, adopt_lock_t); 86e78f53d1SNikolas Klauser template <class Clock, class Duration> 87e78f53d1SNikolas Klauser shared_lock(mutex_type& m, 88e78f53d1SNikolas Klauser const chrono::time_point<Clock, Duration>& abs_time); 89e78f53d1SNikolas Klauser template <class Rep, class Period> 90e78f53d1SNikolas Klauser shared_lock(mutex_type& m, 91e78f53d1SNikolas Klauser const chrono::duration<Rep, Period>& rel_time); 92e78f53d1SNikolas Klauser ~shared_lock(); 93e78f53d1SNikolas Klauser 94e78f53d1SNikolas Klauser shared_lock(shared_lock const&) = delete; 95e78f53d1SNikolas Klauser shared_lock& operator=(shared_lock const&) = delete; 96e78f53d1SNikolas Klauser 97e78f53d1SNikolas Klauser shared_lock(shared_lock&& u) noexcept; 98e78f53d1SNikolas Klauser shared_lock& operator=(shared_lock&& u) noexcept; 99e78f53d1SNikolas Klauser 100e78f53d1SNikolas Klauser void lock(); // blocking 101e78f53d1SNikolas Klauser bool try_lock(); 102e78f53d1SNikolas Klauser template <class Rep, class Period> 103e78f53d1SNikolas Klauser bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 104e78f53d1SNikolas Klauser template <class Clock, class Duration> 105e78f53d1SNikolas Klauser bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 106e78f53d1SNikolas Klauser void unlock(); 107e78f53d1SNikolas Klauser 108e78f53d1SNikolas Klauser // Setters 109e78f53d1SNikolas Klauser void swap(shared_lock& u) noexcept; 110e78f53d1SNikolas Klauser mutex_type* release() noexcept; 111e78f53d1SNikolas Klauser 112e78f53d1SNikolas Klauser // Getters 113e78f53d1SNikolas Klauser bool owns_lock() const noexcept; 114e78f53d1SNikolas Klauser explicit operator bool () const noexcept; 115e78f53d1SNikolas Klauser mutex_type* mutex() const noexcept; 116e78f53d1SNikolas Klauser}; 117e78f53d1SNikolas Klauser 118e78f53d1SNikolas Klausertemplate <class Mutex> 119e78f53d1SNikolas Klauser void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept; 120e78f53d1SNikolas Klauser 121e78f53d1SNikolas Klauser} // std 122e78f53d1SNikolas Klauser 123e78f53d1SNikolas Klauser*/ 124e78f53d1SNikolas Klauser 12573fbae83SNikolas Klauser#include <__cxx03/__config> 126e78f53d1SNikolas Klauser 127e78f53d1SNikolas Klauser#if !defined(_LIBCPP_HAS_NO_THREADS) 128e78f53d1SNikolas Klauser 12973fbae83SNikolas Klauser# include <__cxx03/__chrono/duration.h> 13073fbae83SNikolas Klauser# include <__cxx03/__chrono/steady_clock.h> 13173fbae83SNikolas Klauser# include <__cxx03/__chrono/time_point.h> 13273fbae83SNikolas Klauser# include <__cxx03/__condition_variable/condition_variable.h> 13373fbae83SNikolas Klauser# include <__cxx03/__memory/addressof.h> 13473fbae83SNikolas Klauser# include <__cxx03/__mutex/mutex.h> 13573fbae83SNikolas Klauser# include <__cxx03/__mutex/tag_types.h> 13673fbae83SNikolas Klauser# include <__cxx03/__mutex/unique_lock.h> 13773fbae83SNikolas Klauser# include <__cxx03/__system_error/system_error.h> 13873fbae83SNikolas Klauser# include <__cxx03/__utility/swap.h> 13973fbae83SNikolas Klauser# include <__cxx03/cerrno> 14073fbae83SNikolas Klauser# include <__cxx03/version> 141e78f53d1SNikolas Klauser 142e78f53d1SNikolas Klauser_LIBCPP_PUSH_MACROS 14373fbae83SNikolas Klauser# include <__cxx03/__undef_macros> 144e78f53d1SNikolas Klauser 145e78f53d1SNikolas Klauser# if _LIBCPP_STD_VER >= 14 146e78f53d1SNikolas Klauser 147e78f53d1SNikolas Klauser# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 148e78f53d1SNikolas Klauser# pragma GCC system_header 149e78f53d1SNikolas Klauser# endif 150e78f53d1SNikolas Klauser 151e78f53d1SNikolas Klauser_LIBCPP_BEGIN_NAMESPACE_STD 152e78f53d1SNikolas Klauser 153e78f53d1SNikolas Klauserstruct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base { 154e78f53d1SNikolas Klauser mutex __mut_; 155e78f53d1SNikolas Klauser condition_variable __gate1_; 156e78f53d1SNikolas Klauser condition_variable __gate2_; 157e78f53d1SNikolas Klauser unsigned __state_; 158e78f53d1SNikolas Klauser 159e78f53d1SNikolas Klauser static const unsigned __write_entered_ = 1U << (sizeof(unsigned) * __CHAR_BIT__ - 1); 160e78f53d1SNikolas Klauser static const unsigned __n_readers_ = ~__write_entered_; 161e78f53d1SNikolas Klauser 162e78f53d1SNikolas Klauser __shared_mutex_base(); 163e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI ~__shared_mutex_base() = default; 164e78f53d1SNikolas Klauser 165e78f53d1SNikolas Klauser __shared_mutex_base(const __shared_mutex_base&) = delete; 166e78f53d1SNikolas Klauser __shared_mutex_base& operator=(const __shared_mutex_base&) = delete; 167e78f53d1SNikolas Klauser 168e78f53d1SNikolas Klauser // Exclusive ownership 169e78f53d1SNikolas Klauser void lock(); // blocking 170e78f53d1SNikolas Klauser bool try_lock(); 171e78f53d1SNikolas Klauser void unlock(); 172e78f53d1SNikolas Klauser 173e78f53d1SNikolas Klauser // Shared ownership 174e78f53d1SNikolas Klauser void lock_shared(); // blocking 175e78f53d1SNikolas Klauser bool try_lock_shared(); 176e78f53d1SNikolas Klauser void unlock_shared(); 177e78f53d1SNikolas Klauser 178e78f53d1SNikolas Klauser // typedef implementation-defined native_handle_type; // See 30.2.3 179e78f53d1SNikolas Klauser // native_handle_type native_handle(); // See 30.2.3 180e78f53d1SNikolas Klauser}; 181e78f53d1SNikolas Klauser 182e78f53d1SNikolas Klauser# if _LIBCPP_STD_VER >= 17 183e78f53d1SNikolas Klauserclass _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(__capability__("shared_mutex")) shared_mutex { 184e78f53d1SNikolas Klauser __shared_mutex_base __base_; 185e78f53d1SNikolas Klauser 186e78f53d1SNikolas Klauserpublic: 187e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI shared_mutex() : __base_() {} 188e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI ~shared_mutex() = default; 189e78f53d1SNikolas Klauser 190e78f53d1SNikolas Klauser shared_mutex(const shared_mutex&) = delete; 191e78f53d1SNikolas Klauser shared_mutex& operator=(const shared_mutex&) = delete; 192e78f53d1SNikolas Klauser 193e78f53d1SNikolas Klauser // Exclusive ownership 194e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_capability__()) { 195e78f53d1SNikolas Klauser return __base_.lock(); 196e78f53d1SNikolas Klauser } 197e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) { 198e78f53d1SNikolas Klauser return __base_.try_lock(); 199e78f53d1SNikolas Klauser } 200e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__()) { 201e78f53d1SNikolas Klauser return __base_.unlock(); 202e78f53d1SNikolas Klauser } 203e78f53d1SNikolas Klauser 204e78f53d1SNikolas Klauser // Shared ownership 205e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_shared_capability__()) { 206e78f53d1SNikolas Klauser return __base_.lock_shared(); 207e78f53d1SNikolas Klauser } 208e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool try_lock_shared() 209e78f53d1SNikolas Klauser _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) { 210e78f53d1SNikolas Klauser return __base_.try_lock_shared(); 211e78f53d1SNikolas Klauser } 212e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__()) { 213e78f53d1SNikolas Klauser return __base_.unlock_shared(); 214e78f53d1SNikolas Klauser } 215e78f53d1SNikolas Klauser 216e78f53d1SNikolas Klauser // typedef __shared_mutex_base::native_handle_type native_handle_type; 217e78f53d1SNikolas Klauser // _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return __base::unlock_shared(); } 218e78f53d1SNikolas Klauser}; 219e78f53d1SNikolas Klauser# endif 220e78f53d1SNikolas Klauser 221e78f53d1SNikolas Klauserclass _LIBCPP_EXPORTED_FROM_ABI 222e78f53d1SNikolas Klauser_LIBCPP_THREAD_SAFETY_ANNOTATION(__capability__("shared_timed_mutex")) shared_timed_mutex { 223e78f53d1SNikolas Klauser __shared_mutex_base __base_; 224e78f53d1SNikolas Klauser 225e78f53d1SNikolas Klauserpublic: 226e78f53d1SNikolas Klauser shared_timed_mutex(); 227e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI ~shared_timed_mutex() = default; 228e78f53d1SNikolas Klauser 229e78f53d1SNikolas Klauser shared_timed_mutex(const shared_timed_mutex&) = delete; 230e78f53d1SNikolas Klauser shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; 231e78f53d1SNikolas Klauser 232e78f53d1SNikolas Klauser // Exclusive ownership 233e78f53d1SNikolas Klauser void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_capability__()); 234e78f53d1SNikolas Klauser bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)); 235e78f53d1SNikolas Klauser template <class _Rep, class _Period> 236e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) 237e78f53d1SNikolas Klauser _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) { 238e78f53d1SNikolas Klauser return try_lock_until(chrono::steady_clock::now() + __rel_time); 239e78f53d1SNikolas Klauser } 240e78f53d1SNikolas Klauser template <class _Clock, class _Duration> 241e78f53d1SNikolas Klauser _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool 242e78f53d1SNikolas Klauser try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) 243e78f53d1SNikolas Klauser _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)); 244e78f53d1SNikolas Klauser void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__()); 245e78f53d1SNikolas Klauser 246e78f53d1SNikolas Klauser // Shared ownership 247e78f53d1SNikolas Klauser void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_shared_capability__()); 248e78f53d1SNikolas Klauser bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)); 249e78f53d1SNikolas Klauser template <class _Rep, class _Period> 250e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) 251e78f53d1SNikolas Klauser _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) { 252e78f53d1SNikolas Klauser return try_lock_shared_until(chrono::steady_clock::now() + __rel_time); 253e78f53d1SNikolas Klauser } 254e78f53d1SNikolas Klauser template <class _Clock, class _Duration> 255e78f53d1SNikolas Klauser _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool 256e78f53d1SNikolas Klauser try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) 257e78f53d1SNikolas Klauser _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)); 258e78f53d1SNikolas Klauser void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__()); 259e78f53d1SNikolas Klauser}; 260e78f53d1SNikolas Klauser 261e78f53d1SNikolas Klausertemplate <class _Clock, class _Duration> 262e78f53d1SNikolas Klauserbool shared_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) { 263e78f53d1SNikolas Klauser unique_lock<mutex> __lk(__base_.__mut_); 264e78f53d1SNikolas Klauser if (__base_.__state_ & __base_.__write_entered_) { 265e78f53d1SNikolas Klauser while (true) { 266e78f53d1SNikolas Klauser cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time); 267e78f53d1SNikolas Klauser if ((__base_.__state_ & __base_.__write_entered_) == 0) 268e78f53d1SNikolas Klauser break; 269e78f53d1SNikolas Klauser if (__status == cv_status::timeout) 270e78f53d1SNikolas Klauser return false; 271e78f53d1SNikolas Klauser } 272e78f53d1SNikolas Klauser } 273e78f53d1SNikolas Klauser __base_.__state_ |= __base_.__write_entered_; 274e78f53d1SNikolas Klauser if (__base_.__state_ & __base_.__n_readers_) { 275e78f53d1SNikolas Klauser while (true) { 276e78f53d1SNikolas Klauser cv_status __status = __base_.__gate2_.wait_until(__lk, __abs_time); 277e78f53d1SNikolas Klauser if ((__base_.__state_ & __base_.__n_readers_) == 0) 278e78f53d1SNikolas Klauser break; 279e78f53d1SNikolas Klauser if (__status == cv_status::timeout) { 280e78f53d1SNikolas Klauser __base_.__state_ &= ~__base_.__write_entered_; 281e78f53d1SNikolas Klauser __base_.__gate1_.notify_all(); 282e78f53d1SNikolas Klauser return false; 283e78f53d1SNikolas Klauser } 284e78f53d1SNikolas Klauser } 285e78f53d1SNikolas Klauser } 286e78f53d1SNikolas Klauser return true; 287e78f53d1SNikolas Klauser} 288e78f53d1SNikolas Klauser 289e78f53d1SNikolas Klausertemplate <class _Clock, class _Duration> 290e78f53d1SNikolas Klauserbool shared_timed_mutex::try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) { 291e78f53d1SNikolas Klauser unique_lock<mutex> __lk(__base_.__mut_); 292e78f53d1SNikolas Klauser if ((__base_.__state_ & __base_.__write_entered_) || 293e78f53d1SNikolas Klauser (__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) { 294e78f53d1SNikolas Klauser while (true) { 295e78f53d1SNikolas Klauser cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time); 296e78f53d1SNikolas Klauser if ((__base_.__state_ & __base_.__write_entered_) == 0 && 297e78f53d1SNikolas Klauser (__base_.__state_ & __base_.__n_readers_) < __base_.__n_readers_) 298e78f53d1SNikolas Klauser break; 299e78f53d1SNikolas Klauser if (__status == cv_status::timeout) 300e78f53d1SNikolas Klauser return false; 301e78f53d1SNikolas Klauser } 302e78f53d1SNikolas Klauser } 303e78f53d1SNikolas Klauser unsigned __num_readers = (__base_.__state_ & __base_.__n_readers_) + 1; 304e78f53d1SNikolas Klauser __base_.__state_ &= ~__base_.__n_readers_; 305e78f53d1SNikolas Klauser __base_.__state_ |= __num_readers; 306e78f53d1SNikolas Klauser return true; 307e78f53d1SNikolas Klauser} 308e78f53d1SNikolas Klauser 309e78f53d1SNikolas Klausertemplate <class _Mutex> 310e78f53d1SNikolas Klauserclass shared_lock { 311e78f53d1SNikolas Klauserpublic: 312e78f53d1SNikolas Klauser typedef _Mutex mutex_type; 313e78f53d1SNikolas Klauser 314e78f53d1SNikolas Klauserprivate: 315e78f53d1SNikolas Klauser mutex_type* __m_; 316e78f53d1SNikolas Klauser bool __owns_; 317e78f53d1SNikolas Klauser 318e78f53d1SNikolas Klauserpublic: 319e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI shared_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 320e78f53d1SNikolas Klauser 321e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI explicit shared_lock(mutex_type& __m) : __m_(std::addressof(__m)), __owns_(true) { 322e78f53d1SNikolas Klauser __m_->lock_shared(); 323e78f53d1SNikolas Klauser } 324e78f53d1SNikolas Klauser 325e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 326e78f53d1SNikolas Klauser : __m_(std::addressof(__m)), 327e78f53d1SNikolas Klauser __owns_(false) {} 328e78f53d1SNikolas Klauser 329e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, try_to_lock_t) 330e78f53d1SNikolas Klauser : __m_(std::addressof(__m)), __owns_(__m.try_lock_shared()) {} 331e78f53d1SNikolas Klauser 332e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, adopt_lock_t) : __m_(std::addressof(__m)), __owns_(true) {} 333e78f53d1SNikolas Klauser 334e78f53d1SNikolas Klauser template <class _Clock, class _Duration> 335e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __abs_time) 336e78f53d1SNikolas Klauser : __m_(std::addressof(__m)), __owns_(__m.try_lock_shared_until(__abs_time)) {} 337e78f53d1SNikolas Klauser 338e78f53d1SNikolas Klauser template <class _Rep, class _Period> 339e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __rel_time) 340e78f53d1SNikolas Klauser : __m_(std::addressof(__m)), __owns_(__m.try_lock_shared_for(__rel_time)) {} 341e78f53d1SNikolas Klauser 342e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI ~shared_lock() { 343e78f53d1SNikolas Klauser if (__owns_) 344e78f53d1SNikolas Klauser __m_->unlock_shared(); 345e78f53d1SNikolas Klauser } 346e78f53d1SNikolas Klauser 347e78f53d1SNikolas Klauser shared_lock(shared_lock const&) = delete; 348e78f53d1SNikolas Klauser shared_lock& operator=(shared_lock const&) = delete; 349e78f53d1SNikolas Klauser 350e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI shared_lock(shared_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) { 351e78f53d1SNikolas Klauser __u.__m_ = nullptr; 352e78f53d1SNikolas Klauser __u.__owns_ = false; 353e78f53d1SNikolas Klauser } 354e78f53d1SNikolas Klauser 355e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI shared_lock& operator=(shared_lock&& __u) _NOEXCEPT { 356e78f53d1SNikolas Klauser if (__owns_) 357e78f53d1SNikolas Klauser __m_->unlock_shared(); 358e78f53d1SNikolas Klauser __m_ = nullptr; 359e78f53d1SNikolas Klauser __owns_ = false; 360e78f53d1SNikolas Klauser __m_ = __u.__m_; 361e78f53d1SNikolas Klauser __owns_ = __u.__owns_; 362e78f53d1SNikolas Klauser __u.__m_ = nullptr; 363e78f53d1SNikolas Klauser __u.__owns_ = false; 364e78f53d1SNikolas Klauser return *this; 365e78f53d1SNikolas Klauser } 366e78f53d1SNikolas Klauser 367e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void lock(); 368e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool try_lock(); 369e78f53d1SNikolas Klauser template <class _Rep, class _Period> 370e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time); 371e78f53d1SNikolas Klauser template <class _Clock, class _Duration> 372e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time); 373e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void unlock(); 374e78f53d1SNikolas Klauser 375e78f53d1SNikolas Klauser // Setters 376e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void swap(shared_lock& __u) _NOEXCEPT { 377e78f53d1SNikolas Klauser std::swap(__m_, __u.__m_); 378e78f53d1SNikolas Klauser std::swap(__owns_, __u.__owns_); 379e78f53d1SNikolas Klauser } 380e78f53d1SNikolas Klauser 381e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI mutex_type* release() _NOEXCEPT { 382e78f53d1SNikolas Klauser mutex_type* __m = __m_; 383e78f53d1SNikolas Klauser __m_ = nullptr; 384e78f53d1SNikolas Klauser __owns_ = false; 385e78f53d1SNikolas Klauser return __m; 386e78f53d1SNikolas Klauser } 387e78f53d1SNikolas Klauser 388e78f53d1SNikolas Klauser // Getters 389e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI bool owns_lock() const _NOEXCEPT { return __owns_; } 390e78f53d1SNikolas Klauser 391e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __owns_; } 392e78f53d1SNikolas Klauser 393e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI mutex_type* mutex() const _NOEXCEPT { return __m_; } 394e78f53d1SNikolas Klauser}; 395e78f53d1SNikolas Klauser_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(shared_lock); 396e78f53d1SNikolas Klauser 397e78f53d1SNikolas Klausertemplate <class _Mutex> 398e78f53d1SNikolas Klauservoid shared_lock<_Mutex>::lock() { 399e78f53d1SNikolas Klauser if (__m_ == nullptr) 400e78f53d1SNikolas Klauser __throw_system_error(EPERM, "shared_lock::lock: references null mutex"); 401e78f53d1SNikolas Klauser if (__owns_) 402e78f53d1SNikolas Klauser __throw_system_error(EDEADLK, "shared_lock::lock: already locked"); 403e78f53d1SNikolas Klauser __m_->lock_shared(); 404e78f53d1SNikolas Klauser __owns_ = true; 405e78f53d1SNikolas Klauser} 406e78f53d1SNikolas Klauser 407e78f53d1SNikolas Klausertemplate <class _Mutex> 408e78f53d1SNikolas Klauserbool shared_lock<_Mutex>::try_lock() { 409e78f53d1SNikolas Klauser if (__m_ == nullptr) 410e78f53d1SNikolas Klauser __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex"); 411e78f53d1SNikolas Klauser if (__owns_) 412e78f53d1SNikolas Klauser __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked"); 413e78f53d1SNikolas Klauser __owns_ = __m_->try_lock_shared(); 414e78f53d1SNikolas Klauser return __owns_; 415e78f53d1SNikolas Klauser} 416e78f53d1SNikolas Klauser 417e78f53d1SNikolas Klausertemplate <class _Mutex> 418e78f53d1SNikolas Klausertemplate <class _Rep, class _Period> 419e78f53d1SNikolas Klauserbool shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) { 420e78f53d1SNikolas Klauser if (__m_ == nullptr) 421e78f53d1SNikolas Klauser __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex"); 422e78f53d1SNikolas Klauser if (__owns_) 423e78f53d1SNikolas Klauser __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked"); 424e78f53d1SNikolas Klauser __owns_ = __m_->try_lock_shared_for(__d); 425e78f53d1SNikolas Klauser return __owns_; 426e78f53d1SNikolas Klauser} 427e78f53d1SNikolas Klauser 428e78f53d1SNikolas Klausertemplate <class _Mutex> 429e78f53d1SNikolas Klausertemplate <class _Clock, class _Duration> 430e78f53d1SNikolas Klauserbool shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { 431e78f53d1SNikolas Klauser if (__m_ == nullptr) 432e78f53d1SNikolas Klauser __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex"); 433e78f53d1SNikolas Klauser if (__owns_) 434e78f53d1SNikolas Klauser __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked"); 435e78f53d1SNikolas Klauser __owns_ = __m_->try_lock_shared_until(__t); 436e78f53d1SNikolas Klauser return __owns_; 437e78f53d1SNikolas Klauser} 438e78f53d1SNikolas Klauser 439e78f53d1SNikolas Klausertemplate <class _Mutex> 440e78f53d1SNikolas Klauservoid shared_lock<_Mutex>::unlock() { 441e78f53d1SNikolas Klauser if (!__owns_) 442e78f53d1SNikolas Klauser __throw_system_error(EPERM, "shared_lock::unlock: not locked"); 443e78f53d1SNikolas Klauser __m_->unlock_shared(); 444e78f53d1SNikolas Klauser __owns_ = false; 445e78f53d1SNikolas Klauser} 446e78f53d1SNikolas Klauser 447e78f53d1SNikolas Klausertemplate <class _Mutex> 448e78f53d1SNikolas Klauserinline _LIBCPP_HIDE_FROM_ABI void swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT { 449e78f53d1SNikolas Klauser __x.swap(__y); 450e78f53d1SNikolas Klauser} 451e78f53d1SNikolas Klauser 452e78f53d1SNikolas Klauser_LIBCPP_END_NAMESPACE_STD 453e78f53d1SNikolas Klauser 454e78f53d1SNikolas Klauser# endif // _LIBCPP_STD_VER >= 14 455e78f53d1SNikolas Klauser 456e78f53d1SNikolas Klauser_LIBCPP_POP_MACROS 457e78f53d1SNikolas Klauser 458e78f53d1SNikolas Klauser#endif // !defined(_LIBCPP_HAS_NO_THREADS) 459e78f53d1SNikolas Klauser 460e78f53d1SNikolas Klauser#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 46173fbae83SNikolas Klauser# include <__cxx03/system_error> 462e78f53d1SNikolas Klauser#endif 463e78f53d1SNikolas Klauser 464*ce777190SNikolas Klauser#endif // _LIBCPP___CXX03_SHARED_MUTEX 465