1//===---------------------- shared_mutex.cpp ------------------------------===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "__config" 10#ifndef _LIBCPP_HAS_NO_THREADS 11 12#include "shared_mutex" 13#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) 14#pragma comment(lib, "pthread") 15#endif 16 17_LIBCPP_BEGIN_NAMESPACE_STD 18 19// Shared Mutex Base 20__shared_mutex_base::__shared_mutex_base() 21 : __state_(0) 22{ 23} 24 25// Exclusive ownership 26 27void 28__shared_mutex_base::lock() 29{ 30 unique_lock<mutex> lk(__mut_); 31 while (__state_ & __write_entered_) 32 __gate1_.wait(lk); 33 __state_ |= __write_entered_; 34 while (__state_ & __n_readers_) 35 __gate2_.wait(lk); 36} 37 38bool 39__shared_mutex_base::try_lock() 40{ 41 unique_lock<mutex> lk(__mut_); 42 if (__state_ == 0) 43 { 44 __state_ = __write_entered_; 45 return true; 46 } 47 return false; 48} 49 50void 51__shared_mutex_base::unlock() 52{ 53 lock_guard<mutex> _(__mut_); 54 __state_ = 0; 55 __gate1_.notify_all(); 56} 57 58// Shared ownership 59 60void 61__shared_mutex_base::lock_shared() 62{ 63 unique_lock<mutex> lk(__mut_); 64 while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_) 65 __gate1_.wait(lk); 66 unsigned num_readers = (__state_ & __n_readers_) + 1; 67 __state_ &= ~__n_readers_; 68 __state_ |= num_readers; 69} 70 71bool 72__shared_mutex_base::try_lock_shared() 73{ 74 unique_lock<mutex> lk(__mut_); 75 unsigned num_readers = __state_ & __n_readers_; 76 if (!(__state_ & __write_entered_) && num_readers != __n_readers_) 77 { 78 ++num_readers; 79 __state_ &= ~__n_readers_; 80 __state_ |= num_readers; 81 return true; 82 } 83 return false; 84} 85 86void 87__shared_mutex_base::unlock_shared() 88{ 89 lock_guard<mutex> _(__mut_); 90 unsigned num_readers = (__state_ & __n_readers_) - 1; 91 __state_ &= ~__n_readers_; 92 __state_ |= num_readers; 93 if (__state_ & __write_entered_) 94 { 95 if (num_readers == 0) 96 __gate2_.notify_one(); 97 } 98 else 99 { 100 if (num_readers == __n_readers_ - 1) 101 __gate1_.notify_one(); 102 } 103} 104 105 106// Shared Timed Mutex 107// These routines are here for ABI stability 108shared_timed_mutex::shared_timed_mutex() : __base() {} 109void shared_timed_mutex::lock() { return __base.lock(); } 110bool shared_timed_mutex::try_lock() { return __base.try_lock(); } 111void shared_timed_mutex::unlock() { return __base.unlock(); } 112void shared_timed_mutex::lock_shared() { return __base.lock_shared(); } 113bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); } 114void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); } 115 116_LIBCPP_END_NAMESPACE_STD 117 118#endif // !_LIBCPP_HAS_NO_THREADS 119