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