14f7ab58eSDimitry Andric //===---------------------- shared_mutex.cpp ------------------------------===// 24f7ab58eSDimitry Andric // 34f7ab58eSDimitry Andric // The LLVM Compiler Infrastructure 44f7ab58eSDimitry Andric // 54f7ab58eSDimitry Andric // This file is dual licensed under the MIT and the University of Illinois Open 64f7ab58eSDimitry Andric // Source Licenses. See LICENSE.TXT for details. 74f7ab58eSDimitry Andric // 84f7ab58eSDimitry Andric //===----------------------------------------------------------------------===// 94f7ab58eSDimitry Andric 10d72607e9SDimitry Andric #include "__config" 11d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS 12d72607e9SDimitry Andric 134f7ab58eSDimitry Andric #include "shared_mutex" 144f7ab58eSDimitry Andric 154f7ab58eSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 164f7ab58eSDimitry Andric 17854fa44bSDimitry Andric // Shared Mutex Base __shared_mutex_base()18854fa44bSDimitry Andric__shared_mutex_base::__shared_mutex_base() 194f7ab58eSDimitry Andric : __state_(0) 204f7ab58eSDimitry Andric { 214f7ab58eSDimitry Andric } 224f7ab58eSDimitry Andric 234f7ab58eSDimitry Andric // Exclusive ownership 244f7ab58eSDimitry Andric 254f7ab58eSDimitry Andric void lock()26854fa44bSDimitry Andric__shared_mutex_base::lock() 274f7ab58eSDimitry Andric { 284f7ab58eSDimitry Andric unique_lock<mutex> lk(__mut_); 294f7ab58eSDimitry Andric while (__state_ & __write_entered_) 304f7ab58eSDimitry Andric __gate1_.wait(lk); 314f7ab58eSDimitry Andric __state_ |= __write_entered_; 324f7ab58eSDimitry Andric while (__state_ & __n_readers_) 334f7ab58eSDimitry Andric __gate2_.wait(lk); 344f7ab58eSDimitry Andric } 354f7ab58eSDimitry Andric 364f7ab58eSDimitry Andric bool try_lock()37854fa44bSDimitry Andric__shared_mutex_base::try_lock() 384f7ab58eSDimitry Andric { 394f7ab58eSDimitry Andric unique_lock<mutex> lk(__mut_); 404f7ab58eSDimitry Andric if (__state_ == 0) 414f7ab58eSDimitry Andric { 424f7ab58eSDimitry Andric __state_ = __write_entered_; 434f7ab58eSDimitry Andric return true; 444f7ab58eSDimitry Andric } 454f7ab58eSDimitry Andric return false; 464f7ab58eSDimitry Andric } 474f7ab58eSDimitry Andric 484f7ab58eSDimitry Andric void unlock()49854fa44bSDimitry Andric__shared_mutex_base::unlock() 504f7ab58eSDimitry Andric { 514f7ab58eSDimitry Andric lock_guard<mutex> _(__mut_); 524f7ab58eSDimitry Andric __state_ = 0; 534f7ab58eSDimitry Andric __gate1_.notify_all(); 544f7ab58eSDimitry Andric } 554f7ab58eSDimitry Andric 564f7ab58eSDimitry Andric // Shared ownership 574f7ab58eSDimitry Andric 584f7ab58eSDimitry Andric void lock_shared()59854fa44bSDimitry Andric__shared_mutex_base::lock_shared() 604f7ab58eSDimitry Andric { 614f7ab58eSDimitry Andric unique_lock<mutex> lk(__mut_); 624f7ab58eSDimitry Andric while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_) 634f7ab58eSDimitry Andric __gate1_.wait(lk); 644f7ab58eSDimitry Andric unsigned num_readers = (__state_ & __n_readers_) + 1; 654f7ab58eSDimitry Andric __state_ &= ~__n_readers_; 664f7ab58eSDimitry Andric __state_ |= num_readers; 674f7ab58eSDimitry Andric } 684f7ab58eSDimitry Andric 694f7ab58eSDimitry Andric bool try_lock_shared()70854fa44bSDimitry Andric__shared_mutex_base::try_lock_shared() 714f7ab58eSDimitry Andric { 724f7ab58eSDimitry Andric unique_lock<mutex> lk(__mut_); 734f7ab58eSDimitry Andric unsigned num_readers = __state_ & __n_readers_; 744f7ab58eSDimitry Andric if (!(__state_ & __write_entered_) && num_readers != __n_readers_) 754f7ab58eSDimitry Andric { 764f7ab58eSDimitry Andric ++num_readers; 774f7ab58eSDimitry Andric __state_ &= ~__n_readers_; 784f7ab58eSDimitry Andric __state_ |= num_readers; 794f7ab58eSDimitry Andric return true; 804f7ab58eSDimitry Andric } 814f7ab58eSDimitry Andric return false; 824f7ab58eSDimitry Andric } 834f7ab58eSDimitry Andric 844f7ab58eSDimitry Andric void unlock_shared()85854fa44bSDimitry Andric__shared_mutex_base::unlock_shared() 864f7ab58eSDimitry Andric { 874f7ab58eSDimitry Andric lock_guard<mutex> _(__mut_); 884f7ab58eSDimitry Andric unsigned num_readers = (__state_ & __n_readers_) - 1; 894f7ab58eSDimitry Andric __state_ &= ~__n_readers_; 904f7ab58eSDimitry Andric __state_ |= num_readers; 914f7ab58eSDimitry Andric if (__state_ & __write_entered_) 924f7ab58eSDimitry Andric { 934f7ab58eSDimitry Andric if (num_readers == 0) 944f7ab58eSDimitry Andric __gate2_.notify_one(); 954f7ab58eSDimitry Andric } 964f7ab58eSDimitry Andric else 974f7ab58eSDimitry Andric { 984f7ab58eSDimitry Andric if (num_readers == __n_readers_ - 1) 994f7ab58eSDimitry Andric __gate1_.notify_one(); 1004f7ab58eSDimitry Andric } 1014f7ab58eSDimitry Andric } 1024f7ab58eSDimitry Andric 1034f7ab58eSDimitry Andric 104854fa44bSDimitry Andric // Shared Timed Mutex 105854fa44bSDimitry Andric // These routines are here for ABI stability shared_timed_mutex()106854fa44bSDimitry Andricshared_timed_mutex::shared_timed_mutex() : __base() {} lock()107854fa44bSDimitry Andricvoid shared_timed_mutex::lock() { return __base.lock(); } try_lock()108854fa44bSDimitry Andricbool shared_timed_mutex::try_lock() { return __base.try_lock(); } unlock()109854fa44bSDimitry Andricvoid shared_timed_mutex::unlock() { return __base.unlock(); } lock_shared()110854fa44bSDimitry Andricvoid shared_timed_mutex::lock_shared() { return __base.lock_shared(); } try_lock_shared()111854fa44bSDimitry Andricbool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); } unlock_shared()112854fa44bSDimitry Andricvoid shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); } 113854fa44bSDimitry Andric 1144f7ab58eSDimitry Andric _LIBCPP_END_NAMESPACE_STD 115d72607e9SDimitry Andric 116d72607e9SDimitry Andric #endif // !_LIBCPP_HAS_NO_THREADS 117