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