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