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/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 void* data_; ///< We don't know what the data will be 74 75 /// @} 76 /// @name Do Not Implement 77 /// @{ 78 private: 79 RWMutexImpl(const RWMutexImpl & original) LLVM_DELETED_FUNCTION; 80 void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION; 81 /// @} 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 class SmartRWMutex : public RWMutexImpl { 89 unsigned readers, writers; 90 public: 91 explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { } 92 93 bool reader_acquire() { 94 if (!mt_only || llvm_is_multithreaded()) 95 return RWMutexImpl::reader_acquire(); 96 97 // Single-threaded debugging code. This would be racy in multithreaded 98 // mode, but provides not sanity checks in single threaded mode. 99 ++readers; 100 return true; 101 } 102 103 bool reader_release() { 104 if (!mt_only || llvm_is_multithreaded()) 105 return RWMutexImpl::reader_release(); 106 107 // Single-threaded debugging code. This would be racy in multithreaded 108 // mode, but provides not sanity checks in single threaded mode. 109 assert(readers > 0 && "Reader lock not acquired before release!"); 110 --readers; 111 return true; 112 } 113 114 bool writer_acquire() { 115 if (!mt_only || llvm_is_multithreaded()) 116 return RWMutexImpl::writer_acquire(); 117 118 // Single-threaded debugging code. This would be racy in multithreaded 119 // mode, but provides not sanity checks in single threaded mode. 120 assert(writers == 0 && "Writer lock already acquired!"); 121 ++writers; 122 return true; 123 } 124 125 bool writer_release() { 126 if (!mt_only || llvm_is_multithreaded()) 127 return RWMutexImpl::writer_release(); 128 129 // Single-threaded debugging code. This would be racy in multithreaded 130 // mode, but provides not sanity checks in single threaded mode. 131 assert(writers == 1 && "Writer lock not acquired before release!"); 132 --writers; 133 return true; 134 } 135 136 private: 137 SmartRWMutex(const SmartRWMutex<mt_only> & original); 138 void operator=(const SmartRWMutex<mt_only> &); 139 }; 140 typedef SmartRWMutex<false> RWMutex; 141 142 /// ScopedReader - RAII acquisition of a reader lock 143 template<bool mt_only> 144 struct SmartScopedReader { 145 SmartRWMutex<mt_only>& mutex; 146 147 explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) { 148 mutex.reader_acquire(); 149 } 150 151 ~SmartScopedReader() { 152 mutex.reader_release(); 153 } 154 }; 155 typedef SmartScopedReader<false> ScopedReader; 156 157 /// ScopedWriter - RAII acquisition of a writer lock 158 template<bool mt_only> 159 struct SmartScopedWriter { 160 SmartRWMutex<mt_only>& mutex; 161 162 explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) { 163 mutex.writer_acquire(); 164 } 165 166 ~SmartScopedWriter() { 167 mutex.writer_release(); 168 } 169 }; 170 typedef SmartScopedWriter<false> ScopedWriter; 171 } 172 } 173 174 #endif 175