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 void* data_; ///< We don't know what the data will be 74 75 /// @} 76 /// @name Do Not Implement 77 /// @{ 78 private: 79 MutexImpl(const MutexImpl &) = delete; 80 void operator=(const MutexImpl &) = delete; 81 /// @} 82 }; 83 84 85 /// SmartMutex - A mutex with a compile time constant parameter that 86 /// indicates whether this mutex should become a no-op when we're not 87 /// running in multithreaded mode. 88 template<bool mt_only> 89 class SmartMutex { 90 MutexImpl impl; 91 unsigned acquired; 92 bool recursive; 93 public: 94 explicit SmartMutex(bool rec = true) : impl(rec)95 impl(rec), acquired(0), recursive(rec) { } 96 lock()97 bool lock() { 98 if (!mt_only || llvm_is_multithreaded()) { 99 return impl.acquire(); 100 } else { 101 // Single-threaded debugging code. This would be racy in 102 // multithreaded mode, but provides not sanity checks in single 103 // threaded mode. 104 assert((recursive || acquired == 0) && "Lock already acquired!!"); 105 ++acquired; 106 return true; 107 } 108 } 109 unlock()110 bool unlock() { 111 if (!mt_only || llvm_is_multithreaded()) { 112 return impl.release(); 113 } else { 114 // Single-threaded debugging code. This would be racy in 115 // multithreaded mode, but provides not sanity checks in single 116 // threaded mode. 117 assert(((recursive && acquired) || (acquired == 1)) && 118 "Lock not acquired before release!"); 119 --acquired; 120 return true; 121 } 122 } 123 try_lock()124 bool try_lock() { 125 if (!mt_only || llvm_is_multithreaded()) 126 return impl.tryacquire(); 127 else return true; 128 } 129 130 private: 131 SmartMutex(const SmartMutex<mt_only> & original); 132 void operator=(const SmartMutex<mt_only> &); 133 }; 134 135 /// Mutex - A standard, always enforced mutex. 136 typedef SmartMutex<false> Mutex; 137 138 template<bool mt_only> 139 class SmartScopedLock { 140 SmartMutex<mt_only>& mtx; 141 142 public: SmartScopedLock(SmartMutex<mt_only> & m)143 SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { 144 mtx.lock(); 145 } 146 ~SmartScopedLock()147 ~SmartScopedLock() { 148 mtx.unlock(); 149 } 150 }; 151 152 typedef SmartScopedLock<false> ScopedLock; 153 } 154 } 155 156 #endif 157