LLVM API Documentation
00001 //===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file declares the llvm::sys::RWMutex class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_SUPPORT_RWMUTEX_H 00015 #define LLVM_SUPPORT_RWMUTEX_H 00016 00017 #include "llvm/Support/Compiler.h" 00018 #include "llvm/Support/Threading.h" 00019 #include <cassert> 00020 00021 namespace llvm 00022 { 00023 namespace sys 00024 { 00025 /// @brief Platform agnostic RWMutex class. 00026 class RWMutexImpl 00027 { 00028 /// @name Constructors 00029 /// @{ 00030 public: 00031 00032 /// Initializes the lock but doesn't acquire it. 00033 /// @brief Default Constructor. 00034 explicit RWMutexImpl(); 00035 00036 /// Releases and removes the lock 00037 /// @brief Destructor 00038 ~RWMutexImpl(); 00039 00040 /// @} 00041 /// @name Methods 00042 /// @{ 00043 public: 00044 00045 /// Attempts to unconditionally acquire the lock in reader mode. If the 00046 /// lock is held by a writer, this method will wait until it can acquire 00047 /// the lock. 00048 /// @returns false if any kind of error occurs, true otherwise. 00049 /// @brief Unconditionally acquire the lock in reader mode. 00050 bool reader_acquire(); 00051 00052 /// Attempts to release the lock in reader mode. 00053 /// @returns false if any kind of error occurs, true otherwise. 00054 /// @brief Unconditionally release the lock in reader mode. 00055 bool reader_release(); 00056 00057 /// Attempts to unconditionally acquire the lock in reader mode. If the 00058 /// lock is held by any readers, this method will wait until it can 00059 /// acquire the lock. 00060 /// @returns false if any kind of error occurs, true otherwise. 00061 /// @brief Unconditionally acquire the lock in writer mode. 00062 bool writer_acquire(); 00063 00064 /// Attempts to release the lock in writer mode. 00065 /// @returns false if any kind of error occurs, true otherwise. 00066 /// @brief Unconditionally release the lock in write mode. 00067 bool writer_release(); 00068 00069 //@} 00070 /// @name Platform Dependent Data 00071 /// @{ 00072 private: 00073 void* data_; ///< We don't know what the data will be 00074 00075 /// @} 00076 /// @name Do Not Implement 00077 /// @{ 00078 private: 00079 RWMutexImpl(const RWMutexImpl & original) LLVM_DELETED_FUNCTION; 00080 void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION; 00081 /// @} 00082 }; 00083 00084 /// SmartMutex - An R/W mutex with a compile time constant parameter that 00085 /// indicates whether this mutex should become a no-op when we're not 00086 /// running in multithreaded mode. 00087 template<bool mt_only> 00088 class SmartRWMutex { 00089 RWMutexImpl impl; 00090 unsigned readers, writers; 00091 public: 00092 explicit SmartRWMutex() : impl(), readers(0), writers(0) { } 00093 00094 bool lock_shared() { 00095 if (!mt_only || llvm_is_multithreaded()) 00096 return impl.reader_acquire(); 00097 00098 // Single-threaded debugging code. This would be racy in multithreaded 00099 // mode, but provides not sanity checks in single threaded mode. 00100 ++readers; 00101 return true; 00102 } 00103 00104 bool unlock_shared() { 00105 if (!mt_only || llvm_is_multithreaded()) 00106 return impl.reader_release(); 00107 00108 // Single-threaded debugging code. This would be racy in multithreaded 00109 // mode, but provides not sanity checks in single threaded mode. 00110 assert(readers > 0 && "Reader lock not acquired before release!"); 00111 --readers; 00112 return true; 00113 } 00114 00115 bool lock() { 00116 if (!mt_only || llvm_is_multithreaded()) 00117 return impl.writer_acquire(); 00118 00119 // Single-threaded debugging code. This would be racy in multithreaded 00120 // mode, but provides not sanity checks in single threaded mode. 00121 assert(writers == 0 && "Writer lock already acquired!"); 00122 ++writers; 00123 return true; 00124 } 00125 00126 bool unlock() { 00127 if (!mt_only || llvm_is_multithreaded()) 00128 return impl.writer_release(); 00129 00130 // Single-threaded debugging code. This would be racy in multithreaded 00131 // mode, but provides not sanity checks in single threaded mode. 00132 assert(writers == 1 && "Writer lock not acquired before release!"); 00133 --writers; 00134 return true; 00135 } 00136 00137 private: 00138 SmartRWMutex(const SmartRWMutex<mt_only> & original); 00139 void operator=(const SmartRWMutex<mt_only> &); 00140 }; 00141 typedef SmartRWMutex<false> RWMutex; 00142 00143 /// ScopedReader - RAII acquisition of a reader lock 00144 template<bool mt_only> 00145 struct SmartScopedReader { 00146 SmartRWMutex<mt_only>& mutex; 00147 00148 explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) { 00149 mutex.lock_shared(); 00150 } 00151 00152 ~SmartScopedReader() { 00153 mutex.unlock_shared(); 00154 } 00155 }; 00156 typedef SmartScopedReader<false> ScopedReader; 00157 00158 /// ScopedWriter - RAII acquisition of a writer lock 00159 template<bool mt_only> 00160 struct SmartScopedWriter { 00161 SmartRWMutex<mt_only>& mutex; 00162 00163 explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) { 00164 mutex.lock(); 00165 } 00166 00167 ~SmartScopedWriter() { 00168 mutex.unlock(); 00169 } 00170 }; 00171 typedef SmartScopedWriter<false> ScopedWriter; 00172 } 00173 } 00174 00175 #endif