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 { 00090 MutexImpl impl; 00091 unsigned acquired; 00092 bool recursive; 00093 public: 00094 explicit SmartMutex(bool rec = true) : 00095 impl(rec), acquired(0), recursive(rec) { } 00096 00097 bool lock() { 00098 if (!mt_only || llvm_is_multithreaded()) { 00099 return impl.acquire(); 00100 } else { 00101 // Single-threaded debugging code. This would be racy in 00102 // multithreaded mode, but provides not sanity checks in single 00103 // threaded mode. 00104 assert((recursive || acquired == 0) && "Lock already acquired!!"); 00105 ++acquired; 00106 return true; 00107 } 00108 } 00109 00110 bool unlock() { 00111 if (!mt_only || llvm_is_multithreaded()) { 00112 return impl.release(); 00113 } else { 00114 // Single-threaded debugging code. This would be racy in 00115 // multithreaded mode, but provides not sanity checks in single 00116 // threaded mode. 00117 assert(((recursive && acquired) || (acquired == 1)) && 00118 "Lock not acquired before release!"); 00119 --acquired; 00120 return true; 00121 } 00122 } 00123 00124 bool try_lock() { 00125 if (!mt_only || llvm_is_multithreaded()) 00126 return impl.tryacquire(); 00127 else return true; 00128 } 00129 00130 private: 00131 SmartMutex(const SmartMutex<mt_only> & original); 00132 void operator=(const SmartMutex<mt_only> &); 00133 }; 00134 00135 /// Mutex - A standard, always enforced mutex. 00136 typedef SmartMutex<false> Mutex; 00137 00138 template<bool mt_only> 00139 class SmartScopedLock { 00140 SmartMutex<mt_only>& mtx; 00141 00142 public: 00143 SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { 00144 mtx.lock(); 00145 } 00146 00147 ~SmartScopedLock() { 00148 mtx.unlock(); 00149 } 00150 }; 00151 00152 typedef SmartScopedLock<false> ScopedLock; 00153 } 00154 } 00155 00156 #endif