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