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 &) LLVM_DELETED_FUNCTION; 80 void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION; 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 : public MutexImpl { 90 unsigned acquired; 91 bool recursive; 92 public: 93 explicit SmartMutex(bool rec = true) : MutexImpl(rec)94 MutexImpl(rec), acquired(0), recursive(rec) { } 95 acquire()96 bool acquire() { 97 if (!mt_only || llvm_is_multithreaded()) { 98 return MutexImpl::acquire(); 99 } else { 100 // Single-threaded debugging code. This would be racy in 101 // multithreaded mode, but provides not sanity checks in single 102 // threaded mode. 103 assert((recursive || acquired == 0) && "Lock already acquired!!"); 104 ++acquired; 105 return true; 106 } 107 } 108 release()109 bool release() { 110 if (!mt_only || llvm_is_multithreaded()) { 111 return MutexImpl::release(); 112 } else { 113 // Single-threaded debugging code. This would be racy in 114 // multithreaded mode, but provides not sanity checks in single 115 // threaded mode. 116 assert(((recursive && acquired) || (acquired == 1)) && 117 "Lock not acquired before release!"); 118 --acquired; 119 return true; 120 } 121 } 122 tryacquire()123 bool tryacquire() { 124 if (!mt_only || llvm_is_multithreaded()) 125 return MutexImpl::tryacquire(); 126 else return true; 127 } 128 129 private: 130 SmartMutex(const SmartMutex<mt_only> & original); 131 void operator=(const SmartMutex<mt_only> &); 132 }; 133 134 /// Mutex - A standard, always enforced mutex. 135 typedef SmartMutex<false> Mutex; 136 137 template<bool mt_only> 138 class SmartScopedLock { 139 SmartMutex<mt_only>& mtx; 140 141 public: SmartScopedLock(SmartMutex<mt_only> & m)142 SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { 143 mtx.acquire(); 144 } 145 ~SmartScopedLock()146 ~SmartScopedLock() { 147 mtx.release(); 148 } 149 }; 150 151 typedef SmartScopedLock<false> ScopedLock; 152 } 153 } 154 155 #endif 156