14684ddb6SLionel Sambuc //===---------------------- shared_mutex.cpp ------------------------------===// 24684ddb6SLionel Sambuc // 34684ddb6SLionel Sambuc // The LLVM Compiler Infrastructure 44684ddb6SLionel Sambuc // 54684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open 64684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details. 74684ddb6SLionel Sambuc // 84684ddb6SLionel Sambuc //===----------------------------------------------------------------------===// 94684ddb6SLionel Sambuc 10*0a6a1f1dSLionel Sambuc #include "__config" 11*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS 12*0a6a1f1dSLionel Sambuc 134684ddb6SLionel Sambuc #define _LIBCPP_BUILDING_SHARED_MUTEX 144684ddb6SLionel Sambuc #include "shared_mutex" 154684ddb6SLionel Sambuc 164684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD 174684ddb6SLionel Sambuc 18*0a6a1f1dSLionel Sambuc // Shared Mutex Base __shared_mutex_base()19*0a6a1f1dSLionel Sambuc__shared_mutex_base::__shared_mutex_base() 204684ddb6SLionel Sambuc : __state_(0) 214684ddb6SLionel Sambuc { 224684ddb6SLionel Sambuc } 234684ddb6SLionel Sambuc 244684ddb6SLionel Sambuc // Exclusive ownership 254684ddb6SLionel Sambuc 264684ddb6SLionel Sambuc void lock()27*0a6a1f1dSLionel Sambuc__shared_mutex_base::lock() 284684ddb6SLionel Sambuc { 294684ddb6SLionel Sambuc unique_lock<mutex> lk(__mut_); 304684ddb6SLionel Sambuc while (__state_ & __write_entered_) 314684ddb6SLionel Sambuc __gate1_.wait(lk); 324684ddb6SLionel Sambuc __state_ |= __write_entered_; 334684ddb6SLionel Sambuc while (__state_ & __n_readers_) 344684ddb6SLionel Sambuc __gate2_.wait(lk); 354684ddb6SLionel Sambuc } 364684ddb6SLionel Sambuc 374684ddb6SLionel Sambuc bool try_lock()38*0a6a1f1dSLionel Sambuc__shared_mutex_base::try_lock() 394684ddb6SLionel Sambuc { 404684ddb6SLionel Sambuc unique_lock<mutex> lk(__mut_); 414684ddb6SLionel Sambuc if (__state_ == 0) 424684ddb6SLionel Sambuc { 434684ddb6SLionel Sambuc __state_ = __write_entered_; 444684ddb6SLionel Sambuc return true; 454684ddb6SLionel Sambuc } 464684ddb6SLionel Sambuc return false; 474684ddb6SLionel Sambuc } 484684ddb6SLionel Sambuc 494684ddb6SLionel Sambuc void unlock()50*0a6a1f1dSLionel Sambuc__shared_mutex_base::unlock() 514684ddb6SLionel Sambuc { 524684ddb6SLionel Sambuc lock_guard<mutex> _(__mut_); 534684ddb6SLionel Sambuc __state_ = 0; 544684ddb6SLionel Sambuc __gate1_.notify_all(); 554684ddb6SLionel Sambuc } 564684ddb6SLionel Sambuc 574684ddb6SLionel Sambuc // Shared ownership 584684ddb6SLionel Sambuc 594684ddb6SLionel Sambuc void lock_shared()60*0a6a1f1dSLionel Sambuc__shared_mutex_base::lock_shared() 614684ddb6SLionel Sambuc { 624684ddb6SLionel Sambuc unique_lock<mutex> lk(__mut_); 634684ddb6SLionel Sambuc while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_) 644684ddb6SLionel Sambuc __gate1_.wait(lk); 654684ddb6SLionel Sambuc unsigned num_readers = (__state_ & __n_readers_) + 1; 664684ddb6SLionel Sambuc __state_ &= ~__n_readers_; 674684ddb6SLionel Sambuc __state_ |= num_readers; 684684ddb6SLionel Sambuc } 694684ddb6SLionel Sambuc 704684ddb6SLionel Sambuc bool try_lock_shared()71*0a6a1f1dSLionel Sambuc__shared_mutex_base::try_lock_shared() 724684ddb6SLionel Sambuc { 734684ddb6SLionel Sambuc unique_lock<mutex> lk(__mut_); 744684ddb6SLionel Sambuc unsigned num_readers = __state_ & __n_readers_; 754684ddb6SLionel Sambuc if (!(__state_ & __write_entered_) && num_readers != __n_readers_) 764684ddb6SLionel Sambuc { 774684ddb6SLionel Sambuc ++num_readers; 784684ddb6SLionel Sambuc __state_ &= ~__n_readers_; 794684ddb6SLionel Sambuc __state_ |= num_readers; 804684ddb6SLionel Sambuc return true; 814684ddb6SLionel Sambuc } 824684ddb6SLionel Sambuc return false; 834684ddb6SLionel Sambuc } 844684ddb6SLionel Sambuc 854684ddb6SLionel Sambuc void unlock_shared()86*0a6a1f1dSLionel Sambuc__shared_mutex_base::unlock_shared() 874684ddb6SLionel Sambuc { 884684ddb6SLionel Sambuc lock_guard<mutex> _(__mut_); 894684ddb6SLionel Sambuc unsigned num_readers = (__state_ & __n_readers_) - 1; 904684ddb6SLionel Sambuc __state_ &= ~__n_readers_; 914684ddb6SLionel Sambuc __state_ |= num_readers; 924684ddb6SLionel Sambuc if (__state_ & __write_entered_) 934684ddb6SLionel Sambuc { 944684ddb6SLionel Sambuc if (num_readers == 0) 954684ddb6SLionel Sambuc __gate2_.notify_one(); 964684ddb6SLionel Sambuc } 974684ddb6SLionel Sambuc else 984684ddb6SLionel Sambuc { 994684ddb6SLionel Sambuc if (num_readers == __n_readers_ - 1) 1004684ddb6SLionel Sambuc __gate1_.notify_one(); 1014684ddb6SLionel Sambuc } 1024684ddb6SLionel Sambuc } 1034684ddb6SLionel Sambuc 1044684ddb6SLionel Sambuc 105*0a6a1f1dSLionel Sambuc // Shared Timed Mutex 106*0a6a1f1dSLionel Sambuc // These routines are here for ABI stability shared_timed_mutex()107*0a6a1f1dSLionel Sambucshared_timed_mutex::shared_timed_mutex() : __base() {} lock()108*0a6a1f1dSLionel Sambucvoid shared_timed_mutex::lock() { return __base.lock(); } try_lock()109*0a6a1f1dSLionel Sambucbool shared_timed_mutex::try_lock() { return __base.try_lock(); } unlock()110*0a6a1f1dSLionel Sambucvoid shared_timed_mutex::unlock() { return __base.unlock(); } lock_shared()111*0a6a1f1dSLionel Sambucvoid shared_timed_mutex::lock_shared() { return __base.lock_shared(); } try_lock_shared()112*0a6a1f1dSLionel Sambucbool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); } unlock_shared()113*0a6a1f1dSLionel Sambucvoid shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); } 114*0a6a1f1dSLionel Sambuc 1154684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD 116*0a6a1f1dSLionel Sambuc 117*0a6a1f1dSLionel Sambuc #endif // !_LIBCPP_HAS_NO_THREADS 118