Recommit [NFC] Better encapsulation of llvm::Optional Storage
[llvm-complete.git] / include / llvm / Support / RWMutex.h
blob9cd57cbd65a1da5649212908c2095397e7252fd7
1 //===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares the llvm::sys::RWMutex class.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_SUPPORT_RWMUTEX_H
14 #define LLVM_SUPPORT_RWMUTEX_H
16 #include "llvm/Config/llvm-config.h"
17 #include "llvm/Support/Threading.h"
18 #include <cassert>
20 namespace llvm {
21 namespace sys {
23 /// Platform agnostic RWMutex class.
24 class RWMutexImpl
26 /// @name Constructors
27 /// @{
28 public:
30 /// Initializes the lock but doesn't acquire it.
31 /// Default Constructor.
32 explicit RWMutexImpl();
34 /// @}
35 /// @name Do Not Implement
36 /// @{
37 RWMutexImpl(const RWMutexImpl & original) = delete;
38 RWMutexImpl &operator=(const RWMutexImpl &) = delete;
39 /// @}
41 /// Releases and removes the lock
42 /// Destructor
43 ~RWMutexImpl();
45 /// @}
46 /// @name Methods
47 /// @{
48 public:
50 /// Attempts to unconditionally acquire the lock in reader mode. If the
51 /// lock is held by a writer, this method will wait until it can acquire
52 /// the lock.
53 /// @returns false if any kind of error occurs, true otherwise.
54 /// Unconditionally acquire the lock in reader mode.
55 bool reader_acquire();
57 /// Attempts to release the lock in reader mode.
58 /// @returns false if any kind of error occurs, true otherwise.
59 /// Unconditionally release the lock in reader mode.
60 bool reader_release();
62 /// Attempts to unconditionally acquire the lock in reader mode. If the
63 /// lock is held by any readers, this method will wait until it can
64 /// acquire the lock.
65 /// @returns false if any kind of error occurs, true otherwise.
66 /// Unconditionally acquire the lock in writer mode.
67 bool writer_acquire();
69 /// Attempts to release the lock in writer mode.
70 /// @returns false if any kind of error occurs, true otherwise.
71 /// Unconditionally release the lock in write mode.
72 bool writer_release();
74 //@}
75 /// @name Platform Dependent Data
76 /// @{
77 private:
78 #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
79 void* data_ = nullptr; ///< We don't know what the data will be
80 #endif
83 /// SmartMutex - An R/W mutex with a compile time constant parameter that
84 /// indicates whether this mutex should become a no-op when we're not
85 /// running in multithreaded mode.
86 template<bool mt_only>
87 class SmartRWMutex {
88 RWMutexImpl impl;
89 unsigned readers = 0;
90 unsigned writers = 0;
92 public:
93 explicit SmartRWMutex() = default;
94 SmartRWMutex(const SmartRWMutex<mt_only> & original) = delete;
95 SmartRWMutex<mt_only> &operator=(const SmartRWMutex<mt_only> &) = delete;
97 bool lock_shared() {
98 if (!mt_only || llvm_is_multithreaded())
99 return impl.reader_acquire();
101 // Single-threaded debugging code. This would be racy in multithreaded
102 // mode, but provides not sanity checks in single threaded mode.
103 ++readers;
104 return true;
107 bool unlock_shared() {
108 if (!mt_only || llvm_is_multithreaded())
109 return impl.reader_release();
111 // Single-threaded debugging code. This would be racy in multithreaded
112 // mode, but provides not sanity checks in single threaded mode.
113 assert(readers > 0 && "Reader lock not acquired before release!");
114 --readers;
115 return true;
118 bool lock() {
119 if (!mt_only || llvm_is_multithreaded())
120 return impl.writer_acquire();
122 // Single-threaded debugging code. This would be racy in multithreaded
123 // mode, but provides not sanity checks in single threaded mode.
124 assert(writers == 0 && "Writer lock already acquired!");
125 ++writers;
126 return true;
129 bool unlock() {
130 if (!mt_only || llvm_is_multithreaded())
131 return impl.writer_release();
133 // Single-threaded debugging code. This would be racy in multithreaded
134 // mode, but provides not sanity checks in single threaded mode.
135 assert(writers == 1 && "Writer lock not acquired before release!");
136 --writers;
137 return true;
141 typedef SmartRWMutex<false> RWMutex;
143 /// ScopedReader - RAII acquisition of a reader lock
144 template<bool mt_only>
145 struct SmartScopedReader {
146 SmartRWMutex<mt_only>& mutex;
148 explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
149 mutex.lock_shared();
152 ~SmartScopedReader() {
153 mutex.unlock_shared();
157 typedef SmartScopedReader<false> ScopedReader;
159 /// ScopedWriter - RAII acquisition of a writer lock
160 template<bool mt_only>
161 struct SmartScopedWriter {
162 SmartRWMutex<mt_only>& mutex;
164 explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
165 mutex.lock();
168 ~SmartScopedWriter() {
169 mutex.unlock();
173 typedef SmartScopedWriter<false> ScopedWriter;
175 } // end namespace sys
176 } // end namespace llvm
178 #endif // LLVM_SUPPORT_RWMUTEX_H