Mutex.h revision 249423
1169689Skan//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// 2169689Skan// 3169689Skan// The LLVM Compiler Infrastructure 4169689Skan// 5169689Skan// This file is distributed under the University of Illinois Open Source 6169689Skan// License. See LICENSE.TXT for details. 7169689Skan// 8169689Skan//===----------------------------------------------------------------------===// 9169689Skan// 10169689Skan// This file declares the llvm::sys::Mutex class. 11169689Skan// 12169689Skan//===----------------------------------------------------------------------===// 13169689Skan 14169689Skan#ifndef LLVM_SUPPORT_MUTEX_H 15169689Skan#define LLVM_SUPPORT_MUTEX_H 16169689Skan 17169689Skan#include "llvm/Support/Compiler.h" 18169689Skan#include "llvm/Support/Threading.h" 19169689Skan#include <cassert> 20169689Skan 21169689Skannamespace llvm 22169689Skan{ 23169689Skan namespace sys 24169689Skan { 25169689Skan /// @brief Platform agnostic Mutex class. 26169689Skan class MutexImpl 27169689Skan { 28169689Skan /// @name Constructors 29169689Skan /// @{ 30169689Skan public: 31169689Skan 32169689Skan /// Initializes the lock but doesn't acquire it. if \p recursive is set 33169689Skan /// to false, the lock will not be recursive which makes it cheaper but 34169689Skan /// also more likely to deadlock (same thread can't acquire more than 35169689Skan /// once). 36169689Skan /// @brief Default Constructor. 37169689Skan explicit MutexImpl(bool recursive = true); 38169689Skan 39169689Skan /// Releases and removes the lock 40169689Skan /// @brief Destructor 41169689Skan ~MutexImpl(); 42169689Skan 43169689Skan /// @} 44169689Skan /// @name Methods 45169689Skan /// @{ 46169689Skan public: 47169689Skan 48169689Skan /// Attempts to unconditionally acquire the lock. If the lock is held by 49169689Skan /// another thread, this method will wait until it can acquire the lock. 50169689Skan /// @returns false if any kind of error occurs, true otherwise. 51169689Skan /// @brief Unconditionally acquire the lock. 52169689Skan bool acquire(); 53169689Skan 54169689Skan /// Attempts to release the lock. If the lock is held by the current 55169689Skan /// thread, the lock is released allowing other threads to acquire the 56169689Skan /// lock. 57169689Skan /// @returns false if any kind of error occurs, true otherwise. 58169689Skan /// @brief Unconditionally release the lock. 59169689Skan bool release(); 60169689Skan 61169689Skan /// Attempts to acquire the lock without blocking. If the lock is not 62169689Skan /// available, this function returns false quickly (without blocking). If 63169689Skan /// the lock is available, it is acquired. 64169689Skan /// @returns false if any kind of error occurs or the lock is not 65169689Skan /// available, true otherwise. 66169689Skan /// @brief Try to acquire the lock. 67169689Skan bool tryacquire(); 68169689Skan 69169689Skan //@} 70169689Skan /// @name Platform Dependent Data 71169689Skan /// @{ 72169689Skan private: 73169689Skan void* data_; ///< We don't know what the data will be 74169689Skan 75169689Skan /// @} 76169689Skan /// @name Do Not Implement 77169689Skan /// @{ 78169689Skan private: 79169689Skan MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION; 80169689Skan void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION; 81169689Skan /// @} 82169689Skan }; 83169689Skan 84169689Skan 85169689Skan /// SmartMutex - A mutex with a compile time constant parameter that 86169689Skan /// indicates whether this mutex should become a no-op when we're not 87169689Skan /// running in multithreaded mode. 88169689Skan template<bool mt_only> 89169689Skan class SmartMutex : public MutexImpl { 90169689Skan unsigned acquired; 91169689Skan bool recursive; 92169689Skan public: 93169689Skan explicit SmartMutex(bool rec = true) : 94169689Skan MutexImpl(rec), acquired(0), recursive(rec) { } 95169689Skan 96169689Skan bool acquire() { 97169689Skan if (!mt_only || llvm_is_multithreaded()) { 98169689Skan return MutexImpl::acquire(); 99169689Skan } else { 100169689Skan // Single-threaded debugging code. This would be racy in 101169689Skan // multithreaded mode, but provides not sanity checks in single 102169689Skan // threaded mode. 103169689Skan assert((recursive || acquired == 0) && "Lock already acquired!!"); 104169689Skan ++acquired; 105169689Skan return true; 106169689Skan } 107169689Skan } 108169689Skan 109169689Skan bool release() { 110169689Skan if (!mt_only || llvm_is_multithreaded()) { 111169689Skan return MutexImpl::release(); 112169689Skan } else { 113169689Skan // Single-threaded debugging code. This would be racy in 114169689Skan // multithreaded mode, but provides not sanity checks in single 115169689Skan // threaded mode. 116169689Skan assert(((recursive && acquired) || (acquired == 1)) && 117169689Skan "Lock not acquired before release!"); 118169689Skan --acquired; 119169689Skan return true; 120169689Skan } 121169689Skan } 122169689Skan 123169689Skan bool tryacquire() { 124169689Skan if (!mt_only || llvm_is_multithreaded()) 125169689Skan return MutexImpl::tryacquire(); 126169689Skan else return true; 127169689Skan } 128169689Skan 129169689Skan private: 130169689Skan SmartMutex(const SmartMutex<mt_only> & original); 131169689Skan void operator=(const SmartMutex<mt_only> &); 132169689Skan }; 133169689Skan 134169689Skan /// Mutex - A standard, always enforced mutex. 135169689Skan typedef SmartMutex<false> Mutex; 136169689Skan 137169689Skan template<bool mt_only> 138169689Skan class SmartScopedLock { 139169689Skan SmartMutex<mt_only>& mtx; 140169689Skan 141169689Skan public: 142169689Skan SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { 143169689Skan mtx.acquire(); 144169689Skan } 145169689Skan 146169689Skan ~SmartScopedLock() { 147169689Skan mtx.release(); 148169689Skan } 149169689Skan }; 150169689Skan 151169689Skan typedef SmartScopedLock<false> ScopedLock; 152169689Skan } 153169689Skan} 154169689Skan 155169689Skan#endif 156169689Skan