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