1ead6f169SHoward Hinnant// -*- C++ -*- 2ead6f169SHoward Hinnant//===------------------------ shared_mutex --------------------------------===// 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 125ead6f169SHoward Hinnant#include <__config> 126*2eadbc86SLouis Dionne#include <__availability> 127f56972e2SMarshall 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 147f30c0117SPetr Hosekstruct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("shared_mutex")) 148f30c0117SPetr Hosek__shared_mutex_base 149ead6f169SHoward Hinnant{ 150ead6f169SHoward Hinnant mutex __mut_; 151ead6f169SHoward Hinnant condition_variable __gate1_; 152ead6f169SHoward Hinnant condition_variable __gate2_; 153ead6f169SHoward Hinnant unsigned __state_; 154ead6f169SHoward Hinnant 155ead6f169SHoward Hinnant static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1); 156ead6f169SHoward Hinnant static const unsigned __n_readers_ = ~__write_entered_; 157f69ae471SMarshall Clow 158f69ae471SMarshall Clow __shared_mutex_base(); 159f69ae471SMarshall Clow _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default; 160f69ae471SMarshall Clow 161f69ae471SMarshall Clow __shared_mutex_base(const __shared_mutex_base&) = delete; 162f69ae471SMarshall Clow __shared_mutex_base& operator=(const __shared_mutex_base&) = delete; 163f69ae471SMarshall Clow 164f69ae471SMarshall Clow // Exclusive ownership 165f30c0117SPetr Hosek void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); // blocking 166f30c0117SPetr Hosek bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); 167f30c0117SPetr Hosek void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); 168f69ae471SMarshall Clow 169f69ae471SMarshall Clow // Shared ownership 170f30c0117SPetr Hosek void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_shared_capability()); // blocking 171f30c0117SPetr Hosek bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_shared_capability(true)); 172f30c0117SPetr Hosek void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_shared_capability()); 173f69ae471SMarshall Clow 174f69ae471SMarshall Clow// typedef implementation-defined native_handle_type; // See 30.2.3 175f69ae471SMarshall Clow// native_handle_type native_handle(); // See 30.2.3 176f69ae471SMarshall Clow}; 177f69ae471SMarshall Clow 178f69ae471SMarshall Clow 179f69ae471SMarshall Clow#if _LIBCPP_STD_VER > 14 180e9c66ad9SMehdi Aminiclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex 181f69ae471SMarshall Clow{ 182f69ae471SMarshall Clow __shared_mutex_base __base; 183f69ae471SMarshall Clowpublic: 184ef407482SEric Fiselier _LIBCPP_INLINE_VISIBILITY shared_mutex() : __base() {} 185f69ae471SMarshall Clow _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default; 186f69ae471SMarshall Clow 187f69ae471SMarshall Clow shared_mutex(const shared_mutex&) = delete; 188f69ae471SMarshall Clow shared_mutex& operator=(const shared_mutex&) = delete; 189f69ae471SMarshall Clow 190f69ae471SMarshall Clow // Exclusive ownership 191f69ae471SMarshall Clow _LIBCPP_INLINE_VISIBILITY void lock() { return __base.lock(); } 192f69ae471SMarshall Clow _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); } 193f69ae471SMarshall Clow _LIBCPP_INLINE_VISIBILITY void unlock() { return __base.unlock(); } 194f69ae471SMarshall Clow 195f69ae471SMarshall Clow // Shared ownership 196f69ae471SMarshall Clow _LIBCPP_INLINE_VISIBILITY void lock_shared() { return __base.lock_shared(); } 197f69ae471SMarshall Clow _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); } 198f69ae471SMarshall Clow _LIBCPP_INLINE_VISIBILITY void unlock_shared() { return __base.unlock_shared(); } 199f69ae471SMarshall Clow 200f69ae471SMarshall Clow// typedef __shared_mutex_base::native_handle_type native_handle_type; 201f69ae471SMarshall Clow// _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); } 202f69ae471SMarshall Clow}; 203f69ae471SMarshall Clow#endif 204f69ae471SMarshall Clow 205f69ae471SMarshall Clow 206e9c66ad9SMehdi Aminiclass _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_timed_mutex 207f69ae471SMarshall Clow{ 208f69ae471SMarshall Clow __shared_mutex_base __base; 209ead6f169SHoward Hinnantpublic: 2107ec93f9bSDavid Majnemer shared_timed_mutex(); 2117ec93f9bSDavid Majnemer _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default; 212ead6f169SHoward Hinnant 2137ec93f9bSDavid Majnemer shared_timed_mutex(const shared_timed_mutex&) = delete; 2147ec93f9bSDavid Majnemer shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; 215ead6f169SHoward Hinnant 216ead6f169SHoward Hinnant // Exclusive ownership 217ead6f169SHoward Hinnant void lock(); 218ead6f169SHoward Hinnant bool try_lock(); 219ead6f169SHoward Hinnant template <class _Rep, class _Period> 220ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 221ead6f169SHoward Hinnant bool 222ead6f169SHoward Hinnant try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) 223ead6f169SHoward Hinnant { 224ead6f169SHoward Hinnant return try_lock_until(chrono::steady_clock::now() + __rel_time); 225ead6f169SHoward Hinnant } 226ead6f169SHoward Hinnant template <class _Clock, class _Duration> 227bda3c7dfSShoaib Meenai _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 228ead6f169SHoward Hinnant bool 229ead6f169SHoward Hinnant try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time); 230ead6f169SHoward Hinnant void unlock(); 231ead6f169SHoward Hinnant 232ead6f169SHoward Hinnant // Shared ownership 233ead6f169SHoward Hinnant void lock_shared(); 234ead6f169SHoward Hinnant bool try_lock_shared(); 235ead6f169SHoward Hinnant template <class _Rep, class _Period> 236ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 237ead6f169SHoward Hinnant bool 238ead6f169SHoward Hinnant try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) 239ead6f169SHoward Hinnant { 240ead6f169SHoward Hinnant return try_lock_shared_until(chrono::steady_clock::now() + __rel_time); 241ead6f169SHoward Hinnant } 242ead6f169SHoward Hinnant template <class _Clock, class _Duration> 243bda3c7dfSShoaib Meenai _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 244ead6f169SHoward Hinnant bool 245ead6f169SHoward Hinnant try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time); 246ead6f169SHoward Hinnant void unlock_shared(); 247ead6f169SHoward Hinnant}; 248ead6f169SHoward Hinnant 249ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration> 250ead6f169SHoward Hinnantbool 2517ec93f9bSDavid Majnemershared_timed_mutex::try_lock_until( 252ead6f169SHoward Hinnant const chrono::time_point<_Clock, _Duration>& __abs_time) 253ead6f169SHoward Hinnant{ 254f69ae471SMarshall Clow unique_lock<mutex> __lk(__base.__mut_); 255f69ae471SMarshall Clow if (__base.__state_ & __base.__write_entered_) 256ead6f169SHoward Hinnant { 257ead6f169SHoward Hinnant while (true) 258ead6f169SHoward Hinnant { 259f69ae471SMarshall Clow cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time); 260f69ae471SMarshall Clow if ((__base.__state_ & __base.__write_entered_) == 0) 261ead6f169SHoward Hinnant break; 262ead6f169SHoward Hinnant if (__status == cv_status::timeout) 263ead6f169SHoward Hinnant return false; 264ead6f169SHoward Hinnant } 265ead6f169SHoward Hinnant } 266f69ae471SMarshall Clow __base.__state_ |= __base.__write_entered_; 267f69ae471SMarshall Clow if (__base.__state_ & __base.__n_readers_) 268ead6f169SHoward Hinnant { 269ead6f169SHoward Hinnant while (true) 270ead6f169SHoward Hinnant { 271f69ae471SMarshall Clow cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time); 272f69ae471SMarshall Clow if ((__base.__state_ & __base.__n_readers_) == 0) 273ead6f169SHoward Hinnant break; 274ead6f169SHoward Hinnant if (__status == cv_status::timeout) 275ead6f169SHoward Hinnant { 276f69ae471SMarshall Clow __base.__state_ &= ~__base.__write_entered_; 277f69ae471SMarshall Clow __base.__gate1_.notify_all(); 278ead6f169SHoward Hinnant return false; 279ead6f169SHoward Hinnant } 280ead6f169SHoward Hinnant } 281ead6f169SHoward Hinnant } 282ead6f169SHoward Hinnant return true; 283ead6f169SHoward Hinnant} 284ead6f169SHoward Hinnant 285ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration> 286ead6f169SHoward Hinnantbool 2877ec93f9bSDavid Majnemershared_timed_mutex::try_lock_shared_until( 288ead6f169SHoward Hinnant const chrono::time_point<_Clock, _Duration>& __abs_time) 289ead6f169SHoward Hinnant{ 290f69ae471SMarshall Clow unique_lock<mutex> __lk(__base.__mut_); 291f69ae471SMarshall Clow if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_) 292ead6f169SHoward Hinnant { 293ead6f169SHoward Hinnant while (true) 294ead6f169SHoward Hinnant { 295f69ae471SMarshall Clow cv_status status = __base.__gate1_.wait_until(__lk, __abs_time); 296f69ae471SMarshall Clow if ((__base.__state_ & __base.__write_entered_) == 0 && 297f69ae471SMarshall Clow (__base.__state_ & __base.__n_readers_) < __base.__n_readers_) 298ead6f169SHoward Hinnant break; 299ead6f169SHoward Hinnant if (status == cv_status::timeout) 300ead6f169SHoward Hinnant return false; 301ead6f169SHoward Hinnant } 302ead6f169SHoward Hinnant } 303f69ae471SMarshall Clow unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1; 304f69ae471SMarshall Clow __base.__state_ &= ~__base.__n_readers_; 305f69ae471SMarshall Clow __base.__state_ |= __num_readers; 306ead6f169SHoward Hinnant return true; 307ead6f169SHoward Hinnant} 308ead6f169SHoward Hinnant 309ead6f169SHoward Hinnanttemplate <class _Mutex> 310ead6f169SHoward Hinnantclass shared_lock 311ead6f169SHoward Hinnant{ 312ead6f169SHoward Hinnantpublic: 313ead6f169SHoward Hinnant typedef _Mutex mutex_type; 314ead6f169SHoward Hinnant 315ead6f169SHoward Hinnantprivate: 316ead6f169SHoward Hinnant mutex_type* __m_; 317ead6f169SHoward Hinnant bool __owns_; 318ead6f169SHoward Hinnant 319ead6f169SHoward Hinnantpublic: 320ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 321d08f0d9cSMarshall Clow shared_lock() _NOEXCEPT 322ead6f169SHoward Hinnant : __m_(nullptr), 323ead6f169SHoward Hinnant __owns_(false) 324ead6f169SHoward Hinnant {} 325ead6f169SHoward Hinnant 326ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 327ead6f169SHoward Hinnant explicit shared_lock(mutex_type& __m) 3283126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), 329ead6f169SHoward Hinnant __owns_(true) 330ead6f169SHoward Hinnant {__m_->lock_shared();} 331ead6f169SHoward Hinnant 332ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 333d08f0d9cSMarshall Clow shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 3343126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), 335ead6f169SHoward Hinnant __owns_(false) 336ead6f169SHoward Hinnant {} 337ead6f169SHoward Hinnant 338ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 339ead6f169SHoward Hinnant shared_lock(mutex_type& __m, try_to_lock_t) 3403126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), 341ead6f169SHoward Hinnant __owns_(__m.try_lock_shared()) 342ead6f169SHoward Hinnant {} 343ead6f169SHoward Hinnant 344ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 345ead6f169SHoward Hinnant shared_lock(mutex_type& __m, adopt_lock_t) 3463126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), 347ead6f169SHoward Hinnant __owns_(true) 348ead6f169SHoward Hinnant {} 349ead6f169SHoward Hinnant 350ead6f169SHoward Hinnant template <class _Clock, class _Duration> 351ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 352ead6f169SHoward Hinnant shared_lock(mutex_type& __m, 353ead6f169SHoward Hinnant const chrono::time_point<_Clock, _Duration>& __abs_time) 3543126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), 355ead6f169SHoward Hinnant __owns_(__m.try_lock_shared_until(__abs_time)) 356ead6f169SHoward Hinnant {} 357ead6f169SHoward Hinnant 358ead6f169SHoward Hinnant template <class _Rep, class _Period> 359ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 360ead6f169SHoward Hinnant shared_lock(mutex_type& __m, 361ead6f169SHoward Hinnant const chrono::duration<_Rep, _Period>& __rel_time) 3623126c881SMarshall Clow : __m_(_VSTD::addressof(__m)), 363ead6f169SHoward Hinnant __owns_(__m.try_lock_shared_for(__rel_time)) 364ead6f169SHoward Hinnant {} 365ead6f169SHoward Hinnant 366ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 367ead6f169SHoward Hinnant ~shared_lock() 368ead6f169SHoward Hinnant { 369ead6f169SHoward Hinnant if (__owns_) 370ead6f169SHoward Hinnant __m_->unlock_shared(); 371ead6f169SHoward Hinnant } 372ead6f169SHoward Hinnant 373ead6f169SHoward Hinnant shared_lock(shared_lock const&) = delete; 374ead6f169SHoward Hinnant shared_lock& operator=(shared_lock const&) = delete; 375ead6f169SHoward Hinnant 376ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 377d08f0d9cSMarshall Clow shared_lock(shared_lock&& __u) _NOEXCEPT 378ead6f169SHoward Hinnant : __m_(__u.__m_), 379ead6f169SHoward Hinnant __owns_(__u.__owns_) 380ead6f169SHoward Hinnant { 381ead6f169SHoward Hinnant __u.__m_ = nullptr; 382ead6f169SHoward Hinnant __u.__owns_ = false; 383ead6f169SHoward Hinnant } 384ead6f169SHoward Hinnant 385ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 386d08f0d9cSMarshall Clow shared_lock& operator=(shared_lock&& __u) _NOEXCEPT 387ead6f169SHoward Hinnant { 388ead6f169SHoward Hinnant if (__owns_) 389ead6f169SHoward Hinnant __m_->unlock_shared(); 390ead6f169SHoward Hinnant __m_ = nullptr; 391ead6f169SHoward Hinnant __owns_ = false; 392ead6f169SHoward Hinnant __m_ = __u.__m_; 393ead6f169SHoward Hinnant __owns_ = __u.__owns_; 394ead6f169SHoward Hinnant __u.__m_ = nullptr; 395ead6f169SHoward Hinnant __u.__owns_ = false; 396ead6f169SHoward Hinnant return *this; 397ead6f169SHoward Hinnant } 398ead6f169SHoward Hinnant 399ead6f169SHoward Hinnant void lock(); 400ead6f169SHoward Hinnant bool try_lock(); 401ead6f169SHoward Hinnant template <class Rep, class Period> 402ead6f169SHoward Hinnant bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 403ead6f169SHoward Hinnant template <class Clock, class Duration> 404ead6f169SHoward Hinnant bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 405ead6f169SHoward Hinnant void unlock(); 406ead6f169SHoward Hinnant 407ead6f169SHoward Hinnant // Setters 408ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 409d08f0d9cSMarshall Clow void swap(shared_lock& __u) _NOEXCEPT 410ead6f169SHoward Hinnant { 411ead6f169SHoward Hinnant _VSTD::swap(__m_, __u.__m_); 412ead6f169SHoward Hinnant _VSTD::swap(__owns_, __u.__owns_); 413ead6f169SHoward Hinnant } 414ead6f169SHoward Hinnant 415ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 416d08f0d9cSMarshall Clow mutex_type* release() _NOEXCEPT 417ead6f169SHoward Hinnant { 418ead6f169SHoward Hinnant mutex_type* __m = __m_; 419ead6f169SHoward Hinnant __m_ = nullptr; 420ead6f169SHoward Hinnant __owns_ = false; 421ead6f169SHoward Hinnant return __m; 422ead6f169SHoward Hinnant } 423ead6f169SHoward Hinnant 424ead6f169SHoward Hinnant // Getters 425ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 426d08f0d9cSMarshall Clow bool owns_lock() const _NOEXCEPT {return __owns_;} 427ead6f169SHoward Hinnant 428ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 429d08f0d9cSMarshall Clow explicit operator bool () const _NOEXCEPT {return __owns_;} 430ead6f169SHoward Hinnant 431ead6f169SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 432d08f0d9cSMarshall Clow mutex_type* mutex() const _NOEXCEPT {return __m_;} 433ead6f169SHoward Hinnant}; 434ead6f169SHoward Hinnant 435ead6f169SHoward Hinnanttemplate <class _Mutex> 436ead6f169SHoward Hinnantvoid 437ead6f169SHoward Hinnantshared_lock<_Mutex>::lock() 438ead6f169SHoward Hinnant{ 439ead6f169SHoward Hinnant if (__m_ == nullptr) 440ead6f169SHoward Hinnant __throw_system_error(EPERM, "shared_lock::lock: references null mutex"); 441ead6f169SHoward Hinnant if (__owns_) 442ead6f169SHoward Hinnant __throw_system_error(EDEADLK, "shared_lock::lock: already locked"); 443ead6f169SHoward Hinnant __m_->lock_shared(); 444ead6f169SHoward Hinnant __owns_ = true; 445ead6f169SHoward Hinnant} 446ead6f169SHoward Hinnant 447ead6f169SHoward Hinnanttemplate <class _Mutex> 448ead6f169SHoward Hinnantbool 449ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock() 450ead6f169SHoward Hinnant{ 451ead6f169SHoward Hinnant if (__m_ == nullptr) 452ead6f169SHoward Hinnant __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex"); 453ead6f169SHoward Hinnant if (__owns_) 454ead6f169SHoward Hinnant __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked"); 455ead6f169SHoward Hinnant __owns_ = __m_->try_lock_shared(); 456ead6f169SHoward Hinnant return __owns_; 457ead6f169SHoward Hinnant} 458ead6f169SHoward Hinnant 459ead6f169SHoward Hinnanttemplate <class _Mutex> 460ead6f169SHoward Hinnanttemplate <class _Rep, class _Period> 461ead6f169SHoward Hinnantbool 462ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 463ead6f169SHoward Hinnant{ 464ead6f169SHoward Hinnant if (__m_ == nullptr) 465ead6f169SHoward Hinnant __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex"); 466ead6f169SHoward Hinnant if (__owns_) 467ead6f169SHoward Hinnant __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked"); 468ead6f169SHoward Hinnant __owns_ = __m_->try_lock_shared_for(__d); 469ead6f169SHoward Hinnant return __owns_; 470ead6f169SHoward Hinnant} 471ead6f169SHoward Hinnant 472ead6f169SHoward Hinnanttemplate <class _Mutex> 473ead6f169SHoward Hinnanttemplate <class _Clock, class _Duration> 474ead6f169SHoward Hinnantbool 475ead6f169SHoward Hinnantshared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 476ead6f169SHoward Hinnant{ 477ead6f169SHoward Hinnant if (__m_ == nullptr) 478ead6f169SHoward Hinnant __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex"); 479ead6f169SHoward Hinnant if (__owns_) 480ead6f169SHoward Hinnant __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked"); 481ead6f169SHoward Hinnant __owns_ = __m_->try_lock_shared_until(__t); 482ead6f169SHoward Hinnant return __owns_; 483ead6f169SHoward Hinnant} 484ead6f169SHoward Hinnant 485ead6f169SHoward Hinnanttemplate <class _Mutex> 486ead6f169SHoward Hinnantvoid 487ead6f169SHoward Hinnantshared_lock<_Mutex>::unlock() 488ead6f169SHoward Hinnant{ 489ead6f169SHoward Hinnant if (!__owns_) 490ead6f169SHoward Hinnant __throw_system_error(EPERM, "shared_lock::unlock: not locked"); 491ead6f169SHoward Hinnant __m_->unlock_shared(); 492ead6f169SHoward Hinnant __owns_ = false; 493ead6f169SHoward Hinnant} 494ead6f169SHoward Hinnant 495ead6f169SHoward Hinnanttemplate <class _Mutex> 496ead6f169SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY 497ead6f169SHoward Hinnantvoid 498d08f0d9cSMarshall Clowswap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT 499ead6f169SHoward Hinnant {__x.swap(__y);} 500ead6f169SHoward Hinnant 501ead6f169SHoward Hinnant_LIBCPP_END_NAMESPACE_STD 502ead6f169SHoward Hinnant 503b3fcc67fSJonathan Roelofs#endif // !_LIBCPP_HAS_NO_THREADS 504b3fcc67fSJonathan Roelofs 505ead6f169SHoward Hinnant#endif // _LIBCPP_STD_VER > 11 506ead6f169SHoward Hinnant 507a016efb1SEric Fiselier_LIBCPP_POP_MACROS 508a016efb1SEric Fiselier 509ead6f169SHoward Hinnant#endif // _LIBCPP_SHARED_MUTEX 510