|  | //===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file declares the llvm::sys::Mutex class. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_SUPPORT_MUTEX_H | 
|  | #define LLVM_SUPPORT_MUTEX_H | 
|  |  | 
|  | #include "llvm/Support/Compiler.h" | 
|  | #include "llvm/Support/Threading.h" | 
|  | #include <cassert> | 
|  |  | 
|  | namespace llvm | 
|  | { | 
|  | namespace sys | 
|  | { | 
|  | /// @brief Platform agnostic Mutex class. | 
|  | class MutexImpl | 
|  | { | 
|  | /// @name Constructors | 
|  | /// @{ | 
|  | public: | 
|  |  | 
|  | /// Initializes the lock but doesn't acquire it. if \p recursive is set | 
|  | /// to false, the lock will not be recursive which makes it cheaper but | 
|  | /// also more likely to deadlock (same thread can't acquire more than | 
|  | /// once). | 
|  | /// @brief Default Constructor. | 
|  | explicit MutexImpl(bool recursive = true); | 
|  |  | 
|  | /// Releases and removes the lock | 
|  | /// @brief Destructor | 
|  | ~MutexImpl(); | 
|  |  | 
|  | /// @} | 
|  | /// @name Methods | 
|  | /// @{ | 
|  | public: | 
|  |  | 
|  | /// Attempts to unconditionally acquire the lock. If the lock is held by | 
|  | /// another thread, this method will wait until it can acquire the lock. | 
|  | /// @returns false if any kind of error occurs, true otherwise. | 
|  | /// @brief Unconditionally acquire the lock. | 
|  | bool acquire(); | 
|  |  | 
|  | /// Attempts to release the lock. If the lock is held by the current | 
|  | /// thread, the lock is released allowing other threads to acquire the | 
|  | /// lock. | 
|  | /// @returns false if any kind of error occurs, true otherwise. | 
|  | /// @brief Unconditionally release the lock. | 
|  | bool release(); | 
|  |  | 
|  | /// Attempts to acquire the lock without blocking. If the lock is not | 
|  | /// available, this function returns false quickly (without blocking). If | 
|  | /// the lock is available, it is acquired. | 
|  | /// @returns false if any kind of error occurs or the lock is not | 
|  | /// available, true otherwise. | 
|  | /// @brief Try to acquire the lock. | 
|  | bool tryacquire(); | 
|  |  | 
|  | //@} | 
|  | /// @name Platform Dependent Data | 
|  | /// @{ | 
|  | private: | 
|  | #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0 | 
|  | void* data_; ///< We don't know what the data will be | 
|  | #endif | 
|  |  | 
|  | /// @} | 
|  | /// @name Do Not Implement | 
|  | /// @{ | 
|  | private: | 
|  | MutexImpl(const MutexImpl &) = delete; | 
|  | void operator=(const MutexImpl &) = delete; | 
|  | /// @} | 
|  | }; | 
|  |  | 
|  |  | 
|  | /// SmartMutex - A mutex with a compile time constant parameter that | 
|  | /// indicates whether this mutex should become a no-op when we're not | 
|  | /// running in multithreaded mode. | 
|  | template<bool mt_only> | 
|  | class SmartMutex { | 
|  | MutexImpl impl; | 
|  | unsigned acquired; | 
|  | bool recursive; | 
|  | public: | 
|  | explicit SmartMutex(bool rec = true) : | 
|  | impl(rec), acquired(0), recursive(rec) { } | 
|  |  | 
|  | bool lock() { | 
|  | if (!mt_only || llvm_is_multithreaded()) { | 
|  | return impl.acquire(); | 
|  | } else { | 
|  | // Single-threaded debugging code.  This would be racy in | 
|  | // multithreaded mode, but provides not sanity checks in single | 
|  | // threaded mode. | 
|  | assert((recursive || acquired == 0) && "Lock already acquired!!"); | 
|  | ++acquired; | 
|  | return true; | 
|  | } | 
|  | } | 
|  |  | 
|  | bool unlock() { | 
|  | if (!mt_only || llvm_is_multithreaded()) { | 
|  | return impl.release(); | 
|  | } else { | 
|  | // Single-threaded debugging code.  This would be racy in | 
|  | // multithreaded mode, but provides not sanity checks in single | 
|  | // threaded mode. | 
|  | assert(((recursive && acquired) || (acquired == 1)) && | 
|  | "Lock not acquired before release!"); | 
|  | --acquired; | 
|  | return true; | 
|  | } | 
|  | } | 
|  |  | 
|  | bool try_lock() { | 
|  | if (!mt_only || llvm_is_multithreaded()) | 
|  | return impl.tryacquire(); | 
|  | else return true; | 
|  | } | 
|  |  | 
|  | private: | 
|  | SmartMutex(const SmartMutex<mt_only> & original); | 
|  | void operator=(const SmartMutex<mt_only> &); | 
|  | }; | 
|  |  | 
|  | /// Mutex - A standard, always enforced mutex. | 
|  | typedef SmartMutex<false> Mutex; | 
|  |  | 
|  | template<bool mt_only> | 
|  | class SmartScopedLock  { | 
|  | SmartMutex<mt_only>& mtx; | 
|  |  | 
|  | public: | 
|  | SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { | 
|  | mtx.lock(); | 
|  | } | 
|  |  | 
|  | ~SmartScopedLock() { | 
|  | mtx.unlock(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | typedef SmartScopedLock<false> ScopedLock; | 
|  | } | 
|  | } | 
|  |  | 
|  | #endif |