1 //===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- 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::Mutex class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_SUPPORT_MUTEX_H 15 #define LLVM_SUPPORT_MUTEX_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 Mutex class. 26 class MutexImpl 27 { 28 /// @name Constructors 29 /// @{ 30 public: 31 32 /// Initializes the lock but doesn't acquire it. if \p recursive is set 33 /// to false, the lock will not be recursive which makes it cheaper but 34 /// also more likely to deadlock (same thread can't acquire more than 35 /// once). 36 /// @brief Default Constructor. 37 explicit MutexImpl(bool recursive = true); 38 39 /// Releases and removes the lock 40 /// @brief Destructor 41 ~MutexImpl(); 42 43 /// @} 44 /// @name Methods 45 /// @{ 46 public: 47 48 /// Attempts to unconditionally acquire the lock. If the lock is held by 49 /// another thread, this method will wait until it can acquire the lock. 50 /// @returns false if any kind of error occurs, true otherwise. 51 /// @brief Unconditionally acquire the lock. 52 bool acquire(); 53 54 /// Attempts to release the lock. If the lock is held by the current 55 /// thread, the lock is released allowing other threads to acquire the 56 /// lock. 57 /// @returns false if any kind of error occurs, true otherwise. 58 /// @brief Unconditionally release the lock. 59 bool release(); 60 61 /// Attempts to acquire the lock without blocking. If the lock is not 62 /// available, this function returns false quickly (without blocking). If 63 /// the lock is available, it is acquired. 64 /// @returns false if any kind of error occurs or the lock is not 65 /// available, true otherwise. 66 /// @brief Try to acquire the lock. 67 bool tryacquire(); 68 69 //@} 70 /// @name Platform Dependent Data 71 /// @{ 72 private: 73 #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0 74 void* data_; ///< We don't know what the data will be 75 #endif 76 77 /// @} 78 /// @name Do Not Implement 79 /// @{ 80 private: 81 MutexImpl(const MutexImpl &) = delete; 82 void operator=(const MutexImpl &) = delete; 83 /// @} 84 }; 85 86 87 /// SmartMutex - A mutex with a compile time constant parameter that 88 /// indicates whether this mutex should become a no-op when we're not 89 /// running in multithreaded mode. 90 template<bool mt_only> 91 class SmartMutex { 92 MutexImpl impl; 93 unsigned acquired; 94 bool recursive; 95 public: 96 explicit SmartMutex(bool rec = true) : impl(rec)97 impl(rec), acquired(0), recursive(rec) { } 98 lock()99 bool lock() { 100 if (!mt_only || llvm_is_multithreaded()) { 101 return impl.acquire(); 102 } else { 103 // Single-threaded debugging code. This would be racy in 104 // multithreaded mode, but provides not sanity checks in single 105 // threaded mode. 106 assert((recursive || acquired == 0) && "Lock already acquired!!"); 107 ++acquired; 108 return true; 109 } 110 } 111 unlock()112 bool unlock() { 113 if (!mt_only || llvm_is_multithreaded()) { 114 return impl.release(); 115 } else { 116 // Single-threaded debugging code. This would be racy in 117 // multithreaded mode, but provides not sanity checks in single 118 // threaded mode. 119 assert(((recursive && acquired) || (acquired == 1)) && 120 "Lock not acquired before release!"); 121 --acquired; 122 return true; 123 } 124 } 125 try_lock()126 bool try_lock() { 127 if (!mt_only || llvm_is_multithreaded()) 128 return impl.tryacquire(); 129 else return true; 130 } 131 132 private: 133 SmartMutex(const SmartMutex<mt_only> & original); 134 void operator=(const SmartMutex<mt_only> &); 135 }; 136 137 /// Mutex - A standard, always enforced mutex. 138 typedef SmartMutex<false> Mutex; 139 140 template<bool mt_only> 141 class SmartScopedLock { 142 SmartMutex<mt_only>& mtx; 143 144 public: SmartScopedLock(SmartMutex<mt_only> & m)145 SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { 146 mtx.lock(); 147 } 148 ~SmartScopedLock()149 ~SmartScopedLock() { 150 mtx.unlock(); 151 } 152 }; 153 154 typedef SmartScopedLock<false> ScopedLock; 155 } 156 } 157 158 #endif 159