LLVM API Documentation
00001 //===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- 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::Mutex class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_SUPPORT_MUTEX_H 00015 #define LLVM_SUPPORT_MUTEX_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 Mutex class. 00026 class MutexImpl 00027 { 00028 /// @name Constructors 00029 /// @{ 00030 public: 00031 00032 /// Initializes the lock but doesn't acquire it. if \p recursive is set 00033 /// to false, the lock will not be recursive which makes it cheaper but 00034 /// also more likely to deadlock (same thread can't acquire more than 00035 /// once). 00036 /// @brief Default Constructor. 00037 explicit MutexImpl(bool recursive = true); 00038 00039 /// Releases and removes the lock 00040 /// @brief Destructor 00041 ~MutexImpl(); 00042 00043 /// @} 00044 /// @name Methods 00045 /// @{ 00046 public: 00047 00048 /// Attempts to unconditionally acquire the lock. If the lock is held by 00049 /// another thread, this method will wait until it can acquire the lock. 00050 /// @returns false if any kind of error occurs, true otherwise. 00051 /// @brief Unconditionally acquire the lock. 00052 bool acquire(); 00053 00054 /// Attempts to release the lock. If the lock is held by the current 00055 /// thread, the lock is released allowing other threads to acquire the 00056 /// lock. 00057 /// @returns false if any kind of error occurs, true otherwise. 00058 /// @brief Unconditionally release the lock. 00059 bool release(); 00060 00061 /// Attempts to acquire the lock without blocking. If the lock is not 00062 /// available, this function returns false quickly (without blocking). If 00063 /// the lock is available, it is acquired. 00064 /// @returns false if any kind of error occurs or the lock is not 00065 /// available, true otherwise. 00066 /// @brief Try to acquire the lock. 00067 bool tryacquire(); 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 MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION; 00080 void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION; 00081 /// @} 00082 }; 00083 00084 00085 /// SmartMutex - A mutex with a compile time constant parameter that 00086 /// indicates whether this mutex should become a no-op when we're not 00087 /// running in multithreaded mode. 00088 template<bool mt_only> 00089 class SmartMutex : public MutexImpl { 00090 unsigned acquired; 00091 bool recursive; 00092 public: 00093 explicit SmartMutex(bool rec = true) : 00094 MutexImpl(rec), acquired(0), recursive(rec) { } 00095 00096 bool acquire() { 00097 if (!mt_only || llvm_is_multithreaded()) { 00098 return MutexImpl::acquire(); 00099 } else { 00100 // Single-threaded debugging code. This would be racy in 00101 // multithreaded mode, but provides not sanity checks in single 00102 // threaded mode. 00103 assert((recursive || acquired == 0) && "Lock already acquired!!"); 00104 ++acquired; 00105 return true; 00106 } 00107 } 00108 00109 bool release() { 00110 if (!mt_only || llvm_is_multithreaded()) { 00111 return MutexImpl::release(); 00112 } else { 00113 // Single-threaded debugging code. This would be racy in 00114 // multithreaded mode, but provides not sanity checks in single 00115 // threaded mode. 00116 assert(((recursive && acquired) || (acquired == 1)) && 00117 "Lock not acquired before release!"); 00118 --acquired; 00119 return true; 00120 } 00121 } 00122 00123 bool tryacquire() { 00124 if (!mt_only || llvm_is_multithreaded()) 00125 return MutexImpl::tryacquire(); 00126 else return true; 00127 } 00128 00129 private: 00130 SmartMutex(const SmartMutex<mt_only> & original); 00131 void operator=(const SmartMutex<mt_only> &); 00132 }; 00133 00134 /// Mutex - A standard, always enforced mutex. 00135 typedef SmartMutex<false> Mutex; 00136 00137 template<bool mt_only> 00138 class SmartScopedLock { 00139 SmartMutex<mt_only>& mtx; 00140 00141 public: 00142 SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { 00143 mtx.acquire(); 00144 } 00145 00146 ~SmartScopedLock() { 00147 mtx.release(); 00148 } 00149 }; 00150 00151 typedef SmartScopedLock<false> ScopedLock; 00152 } 00153 } 00154 00155 #endif