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