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_SYSTEM_RWMUTEX_H 15 #define LLVM_SYSTEM_RWMUTEX_H 16 17 #include "llvm/Support/Threading.h" 18 #include <cassert> 19 20 namespace llvm 21 { 22 namespace sys 23 { 24 /// @brief 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 /// @brief Default Constructor. 33 explicit RWMutexImpl(); 34 35 /// Releases and removes the lock 36 /// @brief Destructor 37 ~RWMutexImpl(); 38 39 /// @} 40 /// @name Methods 41 /// @{ 42 public: 43 44 /// Attempts to unconditionally acquire the lock in reader mode. If the 45 /// lock is held by a writer, this method will wait until it can acquire 46 /// the lock. 47 /// @returns false if any kind of error occurs, true otherwise. 48 /// @brief Unconditionally acquire the lock in reader mode. 49 bool reader_acquire(); 50 51 /// Attempts to release the lock in reader mode. 52 /// @returns false if any kind of error occurs, true otherwise. 53 /// @brief Unconditionally release the lock in reader mode. 54 bool reader_release(); 55 56 /// Attempts to unconditionally acquire the lock in reader mode. If the 57 /// lock is held by any readers, this method will wait until it can 58 /// acquire the lock. 59 /// @returns false if any kind of error occurs, true otherwise. 60 /// @brief Unconditionally acquire the lock in writer mode. 61 bool writer_acquire(); 62 63 /// Attempts to release the lock in writer mode. 64 /// @returns false if any kind of error occurs, true otherwise. 65 /// @brief Unconditionally release the lock in write mode. 66 bool writer_release(); 67 68 //@} 69 /// @name Platform Dependent Data 70 /// @{ 71 private: 72 void* data_; ///< We don't know what the data will be 73 74 /// @} 75 /// @name Do Not Implement 76 /// @{ 77 private: 78 RWMutexImpl(const RWMutexImpl & original); 79 void operator=(const RWMutexImpl &); 80 /// @} 81 }; 82 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 : public RWMutexImpl { 88 unsigned readers, writers; 89 public: 90 explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { } 91 92 bool reader_acquire() { 93 if (!mt_only || llvm_is_multithreaded()) 94 return RWMutexImpl::reader_acquire(); 95 96 // Single-threaded debugging code. This would be racy in multithreaded 97 // mode, but provides not sanity checks in single threaded mode. 98 ++readers; 99 return true; 100 } 101 102 bool reader_release() { 103 if (!mt_only || llvm_is_multithreaded()) 104 return RWMutexImpl::reader_release(); 105 106 // Single-threaded debugging code. This would be racy in multithreaded 107 // mode, but provides not sanity checks in single threaded mode. 108 assert(readers > 0 && "Reader lock not acquired before release!"); 109 --readers; 110 return true; 111 } 112 113 bool writer_acquire() { 114 if (!mt_only || llvm_is_multithreaded()) 115 return RWMutexImpl::writer_acquire(); 116 117 // Single-threaded debugging code. This would be racy in multithreaded 118 // mode, but provides not sanity checks in single threaded mode. 119 assert(writers == 0 && "Writer lock already acquired!"); 120 ++writers; 121 return true; 122 } 123 124 bool writer_release() { 125 if (!mt_only || llvm_is_multithreaded()) 126 return RWMutexImpl::writer_release(); 127 128 // Single-threaded debugging code. This would be racy in multithreaded 129 // mode, but provides not sanity checks in single threaded mode. 130 assert(writers == 1 && "Writer lock not acquired before release!"); 131 --writers; 132 return true; 133 } 134 135 private: 136 SmartRWMutex(const SmartRWMutex<mt_only> & original); 137 void operator=(const SmartRWMutex<mt_only> &); 138 }; 139 typedef SmartRWMutex<false> RWMutex; 140 141 /// ScopedReader - RAII acquisition of a reader lock 142 template<bool mt_only> 143 struct SmartScopedReader { 144 SmartRWMutex<mt_only>& mutex; 145 146 explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) { 147 mutex.reader_acquire(); 148 } 149 150 ~SmartScopedReader() { 151 mutex.reader_release(); 152 } 153 }; 154 typedef SmartScopedReader<false> ScopedReader; 155 156 /// ScopedWriter - RAII acquisition of a writer lock 157 template<bool mt_only> 158 struct SmartScopedWriter { 159 SmartRWMutex<mt_only>& mutex; 160 161 explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) { 162 mutex.writer_acquire(); 163 } 164 165 ~SmartScopedWriter() { 166 mutex.writer_release(); 167 } 168 }; 169 typedef SmartScopedWriter<false> ScopedWriter; 170 } 171 } 172 173 #endif 174