LLVM API Documentation

RWMutex.h
Go to the documentation of this file.
00001 //===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- 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::RWMutex class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_SUPPORT_RWMUTEX_H
00015 #define LLVM_SUPPORT_RWMUTEX_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 RWMutex class.
00026     class RWMutexImpl
00027     {
00028     /// @name Constructors
00029     /// @{
00030     public:
00031 
00032       /// Initializes the lock but doesn't acquire it.
00033       /// @brief Default Constructor.
00034       explicit RWMutexImpl();
00035 
00036       /// Releases and removes the lock
00037       /// @brief Destructor
00038       ~RWMutexImpl();
00039 
00040     /// @}
00041     /// @name Methods
00042     /// @{
00043     public:
00044 
00045       /// Attempts to unconditionally acquire the lock in reader mode. If the
00046       /// lock is held by a writer, this method will wait until it can acquire
00047       /// the lock.
00048       /// @returns false if any kind of error occurs, true otherwise.
00049       /// @brief Unconditionally acquire the lock in reader mode.
00050       bool reader_acquire();
00051 
00052       /// Attempts to release the lock in reader mode.
00053       /// @returns false if any kind of error occurs, true otherwise.
00054       /// @brief Unconditionally release the lock in reader mode.
00055       bool reader_release();
00056 
00057       /// Attempts to unconditionally acquire the lock in reader mode. If the
00058       /// lock is held by any readers, this method will wait until it can
00059       /// acquire the lock.
00060       /// @returns false if any kind of error occurs, true otherwise.
00061       /// @brief Unconditionally acquire the lock in writer mode.
00062       bool writer_acquire();
00063 
00064       /// Attempts to release the lock in writer mode.
00065       /// @returns false if any kind of error occurs, true otherwise.
00066       /// @brief Unconditionally release the lock in write mode.
00067       bool writer_release();
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       RWMutexImpl(const RWMutexImpl & original) LLVM_DELETED_FUNCTION;
00080       void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION;
00081     /// @}
00082     };
00083 
00084     /// SmartMutex - An R/W mutex with a compile time constant parameter that
00085     /// indicates whether this mutex should become a no-op when we're not
00086     /// running in multithreaded mode.
00087     template<bool mt_only>
00088     class SmartRWMutex {
00089       RWMutexImpl impl;
00090       unsigned readers, writers;
00091     public:
00092       explicit SmartRWMutex() : impl(), readers(0), writers(0) { }
00093 
00094       bool lock_shared() {
00095         if (!mt_only || llvm_is_multithreaded())
00096           return impl.reader_acquire();
00097 
00098         // Single-threaded debugging code.  This would be racy in multithreaded
00099         // mode, but provides not sanity checks in single threaded mode.
00100         ++readers;
00101         return true;
00102       }
00103 
00104       bool unlock_shared() {
00105         if (!mt_only || llvm_is_multithreaded())
00106           return impl.reader_release();
00107 
00108         // Single-threaded debugging code.  This would be racy in multithreaded
00109         // mode, but provides not sanity checks in single threaded mode.
00110         assert(readers > 0 && "Reader lock not acquired before release!");
00111         --readers;
00112         return true;
00113       }
00114 
00115       bool lock() {
00116         if (!mt_only || llvm_is_multithreaded())
00117           return impl.writer_acquire();
00118 
00119         // Single-threaded debugging code.  This would be racy in multithreaded
00120         // mode, but provides not sanity checks in single threaded mode.
00121         assert(writers == 0 && "Writer lock already acquired!");
00122         ++writers;
00123         return true;
00124       }
00125 
00126       bool unlock() {
00127         if (!mt_only || llvm_is_multithreaded())
00128           return impl.writer_release();
00129 
00130         // Single-threaded debugging code.  This would be racy in multithreaded
00131         // mode, but provides not sanity checks in single threaded mode.
00132         assert(writers == 1 && "Writer lock not acquired before release!");
00133         --writers;
00134         return true;
00135       }
00136 
00137     private:
00138       SmartRWMutex(const SmartRWMutex<mt_only> & original);
00139       void operator=(const SmartRWMutex<mt_only> &);
00140     };
00141     typedef SmartRWMutex<false> RWMutex;
00142 
00143     /// ScopedReader - RAII acquisition of a reader lock
00144     template<bool mt_only>
00145     struct SmartScopedReader {
00146       SmartRWMutex<mt_only>& mutex;
00147 
00148       explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
00149         mutex.lock_shared();
00150       }
00151 
00152       ~SmartScopedReader() {
00153         mutex.unlock_shared();
00154       }
00155     };
00156     typedef SmartScopedReader<false> ScopedReader;
00157 
00158     /// ScopedWriter - RAII acquisition of a writer lock
00159     template<bool mt_only>
00160     struct SmartScopedWriter {
00161       SmartRWMutex<mt_only>& mutex;
00162 
00163       explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
00164         mutex.lock();
00165       }
00166 
00167       ~SmartScopedWriter() {
00168         mutex.unlock();
00169       }
00170     };
00171     typedef SmartScopedWriter<false> ScopedWriter;
00172   }
00173 }
00174 
00175 #endif