1218885Sdim//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file declares the llvm::sys::Mutex class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14249423Sdim#ifndef LLVM_SUPPORT_MUTEX_H 15249423Sdim#define LLVM_SUPPORT_MUTEX_H 16218885Sdim 17243830Sdim#include "llvm/Support/Compiler.h" 18218885Sdim#include "llvm/Support/Threading.h" 19218885Sdim#include <cassert> 20218885Sdim 21218885Sdimnamespace llvm 22218885Sdim{ 23218885Sdim namespace sys 24218885Sdim { 25218885Sdim /// @brief Platform agnostic Mutex class. 26218885Sdim class MutexImpl 27218885Sdim { 28218885Sdim /// @name Constructors 29218885Sdim /// @{ 30218885Sdim public: 31218885Sdim 32218885Sdim /// Initializes the lock but doesn't acquire it. if \p recursive is set 33218885Sdim /// to false, the lock will not be recursive which makes it cheaper but 34218885Sdim /// also more likely to deadlock (same thread can't acquire more than 35218885Sdim /// once). 36218885Sdim /// @brief Default Constructor. 37218885Sdim explicit MutexImpl(bool recursive = true); 38218885Sdim 39218885Sdim /// Releases and removes the lock 40218885Sdim /// @brief Destructor 41218885Sdim ~MutexImpl(); 42218885Sdim 43218885Sdim /// @} 44218885Sdim /// @name Methods 45218885Sdim /// @{ 46218885Sdim public: 47218885Sdim 48218885Sdim /// Attempts to unconditionally acquire the lock. If the lock is held by 49218885Sdim /// another thread, this method will wait until it can acquire the lock. 50218885Sdim /// @returns false if any kind of error occurs, true otherwise. 51218885Sdim /// @brief Unconditionally acquire the lock. 52218885Sdim bool acquire(); 53218885Sdim 54218885Sdim /// Attempts to release the lock. If the lock is held by the current 55218885Sdim /// thread, the lock is released allowing other threads to acquire the 56218885Sdim /// lock. 57218885Sdim /// @returns false if any kind of error occurs, true otherwise. 58218885Sdim /// @brief Unconditionally release the lock. 59218885Sdim bool release(); 60218885Sdim 61218885Sdim /// Attempts to acquire the lock without blocking. If the lock is not 62218885Sdim /// available, this function returns false quickly (without blocking). If 63218885Sdim /// the lock is available, it is acquired. 64218885Sdim /// @returns false if any kind of error occurs or the lock is not 65218885Sdim /// available, true otherwise. 66218885Sdim /// @brief Try to acquire the lock. 67218885Sdim bool tryacquire(); 68218885Sdim 69218885Sdim //@} 70218885Sdim /// @name Platform Dependent Data 71218885Sdim /// @{ 72218885Sdim private: 73218885Sdim void* data_; ///< We don't know what the data will be 74218885Sdim 75218885Sdim /// @} 76218885Sdim /// @name Do Not Implement 77218885Sdim /// @{ 78218885Sdim private: 79243830Sdim MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION; 80243830Sdim void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION; 81218885Sdim /// @} 82218885Sdim }; 83218885Sdim 84218885Sdim 85218885Sdim /// SmartMutex - A mutex with a compile time constant parameter that 86218885Sdim /// indicates whether this mutex should become a no-op when we're not 87218885Sdim /// running in multithreaded mode. 88218885Sdim template<bool mt_only> 89218885Sdim class SmartMutex : public MutexImpl { 90218885Sdim unsigned acquired; 91218885Sdim bool recursive; 92218885Sdim public: 93218885Sdim explicit SmartMutex(bool rec = true) : 94218885Sdim MutexImpl(rec), acquired(0), recursive(rec) { } 95218885Sdim 96218885Sdim bool acquire() { 97218885Sdim if (!mt_only || llvm_is_multithreaded()) { 98218885Sdim return MutexImpl::acquire(); 99218885Sdim } else { 100218885Sdim // Single-threaded debugging code. This would be racy in 101218885Sdim // multithreaded mode, but provides not sanity checks in single 102218885Sdim // threaded mode. 103218885Sdim assert((recursive || acquired == 0) && "Lock already acquired!!"); 104218885Sdim ++acquired; 105218885Sdim return true; 106218885Sdim } 107218885Sdim } 108218885Sdim 109218885Sdim bool release() { 110218885Sdim if (!mt_only || llvm_is_multithreaded()) { 111218885Sdim return MutexImpl::release(); 112218885Sdim } else { 113218885Sdim // Single-threaded debugging code. This would be racy in 114218885Sdim // multithreaded mode, but provides not sanity checks in single 115218885Sdim // threaded mode. 116218885Sdim assert(((recursive && acquired) || (acquired == 1)) && 117218885Sdim "Lock not acquired before release!"); 118218885Sdim --acquired; 119218885Sdim return true; 120218885Sdim } 121218885Sdim } 122218885Sdim 123218885Sdim bool tryacquire() { 124218885Sdim if (!mt_only || llvm_is_multithreaded()) 125218885Sdim return MutexImpl::tryacquire(); 126218885Sdim else return true; 127218885Sdim } 128218885Sdim 129218885Sdim private: 130218885Sdim SmartMutex(const SmartMutex<mt_only> & original); 131218885Sdim void operator=(const SmartMutex<mt_only> &); 132218885Sdim }; 133218885Sdim 134218885Sdim /// Mutex - A standard, always enforced mutex. 135218885Sdim typedef SmartMutex<false> Mutex; 136218885Sdim 137218885Sdim template<bool mt_only> 138218885Sdim class SmartScopedLock { 139218885Sdim SmartMutex<mt_only>& mtx; 140218885Sdim 141218885Sdim public: 142218885Sdim SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { 143218885Sdim mtx.acquire(); 144218885Sdim } 145218885Sdim 146218885Sdim ~SmartScopedLock() { 147218885Sdim mtx.release(); 148218885Sdim } 149218885Sdim }; 150218885Sdim 151218885Sdim typedef SmartScopedLock<false> ScopedLock; 152218885Sdim } 153218885Sdim} 154218885Sdim 155218885Sdim#endif 156