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