xref: /minix3/external/bsd/libc++/dist/libcxx/src/shared_mutex.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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 Sambuc shared_timed_mutex::shared_timed_mutex() : __base() {}
lock()108*0a6a1f1dSLionel Sambuc void shared_timed_mutex::lock()     { return __base.lock(); }
try_lock()109*0a6a1f1dSLionel Sambuc bool shared_timed_mutex::try_lock() { return __base.try_lock(); }
unlock()110*0a6a1f1dSLionel Sambuc void shared_timed_mutex::unlock()   { return __base.unlock(); }
lock_shared()111*0a6a1f1dSLionel Sambuc void shared_timed_mutex::lock_shared() { return __base.lock_shared(); }
try_lock_shared()112*0a6a1f1dSLionel Sambuc bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); }
unlock_shared()113*0a6a1f1dSLionel Sambuc void 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