| //===- 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 |