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