xref: /netbsd-src/external/apache2/llvm/dist/libcxx/src/shared_mutex.cpp (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
1*4d6fc14bSjoerg //===---------------------- shared_mutex.cpp ------------------------------===//
2*4d6fc14bSjoerg //
3*4d6fc14bSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4d6fc14bSjoerg // See https://llvm.org/LICENSE.txt for license information.
5*4d6fc14bSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4d6fc14bSjoerg //
7*4d6fc14bSjoerg //===----------------------------------------------------------------------===//
8*4d6fc14bSjoerg 
9*4d6fc14bSjoerg #include "__config"
10*4d6fc14bSjoerg #ifndef _LIBCPP_HAS_NO_THREADS
11*4d6fc14bSjoerg 
12*4d6fc14bSjoerg #include "shared_mutex"
13*4d6fc14bSjoerg #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
14*4d6fc14bSjoerg #pragma comment(lib, "pthread")
15*4d6fc14bSjoerg #endif
16*4d6fc14bSjoerg 
17*4d6fc14bSjoerg _LIBCPP_BEGIN_NAMESPACE_STD
18*4d6fc14bSjoerg 
19*4d6fc14bSjoerg // Shared Mutex Base
__shared_mutex_base()20*4d6fc14bSjoerg __shared_mutex_base::__shared_mutex_base()
21*4d6fc14bSjoerg     : __state_(0)
22*4d6fc14bSjoerg {
23*4d6fc14bSjoerg }
24*4d6fc14bSjoerg 
25*4d6fc14bSjoerg // Exclusive ownership
26*4d6fc14bSjoerg 
27*4d6fc14bSjoerg void
lock()28*4d6fc14bSjoerg __shared_mutex_base::lock()
29*4d6fc14bSjoerg {
30*4d6fc14bSjoerg     unique_lock<mutex> lk(__mut_);
31*4d6fc14bSjoerg     while (__state_ & __write_entered_)
32*4d6fc14bSjoerg         __gate1_.wait(lk);
33*4d6fc14bSjoerg     __state_ |= __write_entered_;
34*4d6fc14bSjoerg     while (__state_ & __n_readers_)
35*4d6fc14bSjoerg         __gate2_.wait(lk);
36*4d6fc14bSjoerg }
37*4d6fc14bSjoerg 
38*4d6fc14bSjoerg bool
try_lock()39*4d6fc14bSjoerg __shared_mutex_base::try_lock()
40*4d6fc14bSjoerg {
41*4d6fc14bSjoerg     unique_lock<mutex> lk(__mut_);
42*4d6fc14bSjoerg     if (__state_ == 0)
43*4d6fc14bSjoerg     {
44*4d6fc14bSjoerg         __state_ = __write_entered_;
45*4d6fc14bSjoerg         return true;
46*4d6fc14bSjoerg     }
47*4d6fc14bSjoerg     return false;
48*4d6fc14bSjoerg }
49*4d6fc14bSjoerg 
50*4d6fc14bSjoerg void
unlock()51*4d6fc14bSjoerg __shared_mutex_base::unlock()
52*4d6fc14bSjoerg {
53*4d6fc14bSjoerg     lock_guard<mutex> _(__mut_);
54*4d6fc14bSjoerg     __state_ = 0;
55*4d6fc14bSjoerg     __gate1_.notify_all();
56*4d6fc14bSjoerg }
57*4d6fc14bSjoerg 
58*4d6fc14bSjoerg // Shared ownership
59*4d6fc14bSjoerg 
60*4d6fc14bSjoerg void
lock_shared()61*4d6fc14bSjoerg __shared_mutex_base::lock_shared()
62*4d6fc14bSjoerg {
63*4d6fc14bSjoerg     unique_lock<mutex> lk(__mut_);
64*4d6fc14bSjoerg     while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
65*4d6fc14bSjoerg         __gate1_.wait(lk);
66*4d6fc14bSjoerg     unsigned num_readers = (__state_ & __n_readers_) + 1;
67*4d6fc14bSjoerg     __state_ &= ~__n_readers_;
68*4d6fc14bSjoerg     __state_ |= num_readers;
69*4d6fc14bSjoerg }
70*4d6fc14bSjoerg 
71*4d6fc14bSjoerg bool
try_lock_shared()72*4d6fc14bSjoerg __shared_mutex_base::try_lock_shared()
73*4d6fc14bSjoerg {
74*4d6fc14bSjoerg     unique_lock<mutex> lk(__mut_);
75*4d6fc14bSjoerg     unsigned num_readers = __state_ & __n_readers_;
76*4d6fc14bSjoerg     if (!(__state_ & __write_entered_) && num_readers != __n_readers_)
77*4d6fc14bSjoerg     {
78*4d6fc14bSjoerg         ++num_readers;
79*4d6fc14bSjoerg         __state_ &= ~__n_readers_;
80*4d6fc14bSjoerg         __state_ |= num_readers;
81*4d6fc14bSjoerg         return true;
82*4d6fc14bSjoerg     }
83*4d6fc14bSjoerg     return false;
84*4d6fc14bSjoerg }
85*4d6fc14bSjoerg 
86*4d6fc14bSjoerg void
unlock_shared()87*4d6fc14bSjoerg __shared_mutex_base::unlock_shared()
88*4d6fc14bSjoerg {
89*4d6fc14bSjoerg     lock_guard<mutex> _(__mut_);
90*4d6fc14bSjoerg     unsigned num_readers = (__state_ & __n_readers_) - 1;
91*4d6fc14bSjoerg     __state_ &= ~__n_readers_;
92*4d6fc14bSjoerg     __state_ |= num_readers;
93*4d6fc14bSjoerg     if (__state_ & __write_entered_)
94*4d6fc14bSjoerg     {
95*4d6fc14bSjoerg         if (num_readers == 0)
96*4d6fc14bSjoerg             __gate2_.notify_one();
97*4d6fc14bSjoerg     }
98*4d6fc14bSjoerg     else
99*4d6fc14bSjoerg     {
100*4d6fc14bSjoerg         if (num_readers == __n_readers_ - 1)
101*4d6fc14bSjoerg             __gate1_.notify_one();
102*4d6fc14bSjoerg     }
103*4d6fc14bSjoerg }
104*4d6fc14bSjoerg 
105*4d6fc14bSjoerg 
106*4d6fc14bSjoerg // Shared Timed Mutex
107*4d6fc14bSjoerg // These routines are here for ABI stability
shared_timed_mutex()108*4d6fc14bSjoerg shared_timed_mutex::shared_timed_mutex() : __base() {}
lock()109*4d6fc14bSjoerg void shared_timed_mutex::lock()     { return __base.lock(); }
try_lock()110*4d6fc14bSjoerg bool shared_timed_mutex::try_lock() { return __base.try_lock(); }
unlock()111*4d6fc14bSjoerg void shared_timed_mutex::unlock()   { return __base.unlock(); }
lock_shared()112*4d6fc14bSjoerg void shared_timed_mutex::lock_shared() { return __base.lock_shared(); }
try_lock_shared()113*4d6fc14bSjoerg bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); }
unlock_shared()114*4d6fc14bSjoerg void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); }
115*4d6fc14bSjoerg 
116*4d6fc14bSjoerg _LIBCPP_END_NAMESPACE_STD
117*4d6fc14bSjoerg 
118*4d6fc14bSjoerg #endif // !_LIBCPP_HAS_NO_THREADS
119