LLVM API Documentation

Mutex.h
Go to the documentation of this file.
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