xref: /aosp_15_r20/external/llvm/include/llvm/Support/RWMutex.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1 //===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file declares the llvm::sys::RWMutex class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_SUPPORT_RWMUTEX_H
15 #define LLVM_SUPPORT_RWMUTEX_H
16 
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/Threading.h"
19 #include <cassert>
20 
21 namespace llvm
22 {
23   namespace sys
24   {
25     /// @brief Platform agnostic RWMutex class.
26     class RWMutexImpl
27     {
28     /// @name Constructors
29     /// @{
30     public:
31 
32       /// Initializes the lock but doesn't acquire it.
33       /// @brief Default Constructor.
34       explicit RWMutexImpl();
35 
36       /// Releases and removes the lock
37       /// @brief Destructor
38       ~RWMutexImpl();
39 
40     /// @}
41     /// @name Methods
42     /// @{
43     public:
44 
45       /// Attempts to unconditionally acquire the lock in reader mode. If the
46       /// lock is held by a writer, this method will wait until it can acquire
47       /// the lock.
48       /// @returns false if any kind of error occurs, true otherwise.
49       /// @brief Unconditionally acquire the lock in reader mode.
50       bool reader_acquire();
51 
52       /// Attempts to release the lock in reader mode.
53       /// @returns false if any kind of error occurs, true otherwise.
54       /// @brief Unconditionally release the lock in reader mode.
55       bool reader_release();
56 
57       /// Attempts to unconditionally acquire the lock in reader mode. If the
58       /// lock is held by any readers, this method will wait until it can
59       /// acquire the lock.
60       /// @returns false if any kind of error occurs, true otherwise.
61       /// @brief Unconditionally acquire the lock in writer mode.
62       bool writer_acquire();
63 
64       /// Attempts to release the lock in writer mode.
65       /// @returns false if any kind of error occurs, true otherwise.
66       /// @brief Unconditionally release the lock in write mode.
67       bool writer_release();
68 
69     //@}
70     /// @name Platform Dependent Data
71     /// @{
72     private:
73 #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
74       void* data_; ///< We don't know what the data will be
75 #endif
76 
77     /// @}
78     /// @name Do Not Implement
79     /// @{
80     private:
81       RWMutexImpl(const RWMutexImpl & original) = delete;
82       void operator=(const RWMutexImpl &) = delete;
83     /// @}
84     };
85 
86     /// SmartMutex - An R/W mutex with a compile time constant parameter that
87     /// indicates whether this mutex should become a no-op when we're not
88     /// running in multithreaded mode.
89     template<bool mt_only>
90     class SmartRWMutex {
91       RWMutexImpl impl;
92       unsigned readers, writers;
93     public:
SmartRWMutex()94       explicit SmartRWMutex() : impl(), readers(0), writers(0) { }
95 
lock_shared()96       bool lock_shared() {
97         if (!mt_only || llvm_is_multithreaded())
98           return impl.reader_acquire();
99 
100         // Single-threaded debugging code.  This would be racy in multithreaded
101         // mode, but provides not sanity checks in single threaded mode.
102         ++readers;
103         return true;
104       }
105 
unlock_shared()106       bool unlock_shared() {
107         if (!mt_only || llvm_is_multithreaded())
108           return impl.reader_release();
109 
110         // Single-threaded debugging code.  This would be racy in multithreaded
111         // mode, but provides not sanity checks in single threaded mode.
112         assert(readers > 0 && "Reader lock not acquired before release!");
113         --readers;
114         return true;
115       }
116 
lock()117       bool lock() {
118         if (!mt_only || llvm_is_multithreaded())
119           return impl.writer_acquire();
120 
121         // Single-threaded debugging code.  This would be racy in multithreaded
122         // mode, but provides not sanity checks in single threaded mode.
123         assert(writers == 0 && "Writer lock already acquired!");
124         ++writers;
125         return true;
126       }
127 
unlock()128       bool unlock() {
129         if (!mt_only || llvm_is_multithreaded())
130           return impl.writer_release();
131 
132         // Single-threaded debugging code.  This would be racy in multithreaded
133         // mode, but provides not sanity checks in single threaded mode.
134         assert(writers == 1 && "Writer lock not acquired before release!");
135         --writers;
136         return true;
137       }
138 
139     private:
140       SmartRWMutex(const SmartRWMutex<mt_only> & original);
141       void operator=(const SmartRWMutex<mt_only> &);
142     };
143     typedef SmartRWMutex<false> RWMutex;
144 
145     /// ScopedReader - RAII acquisition of a reader lock
146     template<bool mt_only>
147     struct SmartScopedReader {
148       SmartRWMutex<mt_only>& mutex;
149 
SmartScopedReaderSmartScopedReader150       explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
151         mutex.lock_shared();
152       }
153 
~SmartScopedReaderSmartScopedReader154       ~SmartScopedReader() {
155         mutex.unlock_shared();
156       }
157     };
158     typedef SmartScopedReader<false> ScopedReader;
159 
160     /// ScopedWriter - RAII acquisition of a writer lock
161     template<bool mt_only>
162     struct SmartScopedWriter {
163       SmartRWMutex<mt_only>& mutex;
164 
SmartScopedWriterSmartScopedWriter165       explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
166         mutex.lock();
167       }
168 
~SmartScopedWriterSmartScopedWriter169       ~SmartScopedWriter() {
170         mutex.unlock();
171       }
172     };
173     typedef SmartScopedWriter<false> ScopedWriter;
174   }
175 }
176 
177 #endif
178