Home | History | Annotate | Download | only in Support
      1 //===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file declares the llvm::sys::RWMutex class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_SUPPORT_RWMUTEX_H
     15 #define LLVM_SUPPORT_RWMUTEX_H
     16 
     17 #include "llvm/Support/Compiler.h"
     18 #include "llvm/Support/Threading.h"
     19 #include <cassert>
     20 
     21 namespace llvm
     22 {
     23   namespace sys
     24   {
     25     /// @brief Platform agnostic RWMutex class.
     26     class RWMutexImpl
     27     {
     28     /// @name Constructors
     29     /// @{
     30     public:
     31 
     32       /// Initializes the lock but doesn't acquire it.
     33       /// @brief Default Constructor.
     34       explicit RWMutexImpl();
     35 
     36       /// Releases and removes the lock
     37       /// @brief Destructor
     38       ~RWMutexImpl();
     39 
     40     /// @}
     41     /// @name Methods
     42     /// @{
     43     public:
     44 
     45       /// Attempts to unconditionally acquire the lock in reader mode. If the
     46       /// lock is held by a writer, this method will wait until it can acquire
     47       /// the lock.
     48       /// @returns false if any kind of error occurs, true otherwise.
     49       /// @brief Unconditionally acquire the lock in reader mode.
     50       bool reader_acquire();
     51 
     52       /// Attempts to release the lock in reader mode.
     53       /// @returns false if any kind of error occurs, true otherwise.
     54       /// @brief Unconditionally release the lock in reader mode.
     55       bool reader_release();
     56 
     57       /// Attempts to unconditionally acquire the lock in reader mode. If the
     58       /// lock is held by any readers, this method will wait until it can
     59       /// acquire the lock.
     60       /// @returns false if any kind of error occurs, true otherwise.
     61       /// @brief Unconditionally acquire the lock in writer mode.
     62       bool writer_acquire();
     63 
     64       /// Attempts to release the lock in writer mode.
     65       /// @returns false if any kind of error occurs, true otherwise.
     66       /// @brief Unconditionally release the lock in write mode.
     67       bool writer_release();
     68 
     69     //@}
     70     /// @name Platform Dependent Data
     71     /// @{
     72     private:
     73       void* data_; ///< We don't know what the data will be
     74 
     75     /// @}
     76     /// @name Do Not Implement
     77     /// @{
     78     private:
     79       RWMutexImpl(const RWMutexImpl & original) = delete;
     80       void operator=(const RWMutexImpl &) = delete;
     81     /// @}
     82     };
     83 
     84     /// SmartMutex - An R/W mutex with a compile time constant parameter that
     85     /// indicates whether this mutex should become a no-op when we're not
     86     /// running in multithreaded mode.
     87     template<bool mt_only>
     88     class SmartRWMutex {
     89       RWMutexImpl impl;
     90       unsigned readers, writers;
     91     public:
     92       explicit SmartRWMutex() : impl(), readers(0), writers(0) { }
     93 
     94       bool lock_shared() {
     95         if (!mt_only || llvm_is_multithreaded())
     96           return impl.reader_acquire();
     97 
     98         // Single-threaded debugging code.  This would be racy in multithreaded
     99         // mode, but provides not sanity checks in single threaded mode.
    100         ++readers;
    101         return true;
    102       }
    103 
    104       bool unlock_shared() {
    105         if (!mt_only || llvm_is_multithreaded())
    106           return impl.reader_release();
    107 
    108         // Single-threaded debugging code.  This would be racy in multithreaded
    109         // mode, but provides not sanity checks in single threaded mode.
    110         assert(readers > 0 && "Reader lock not acquired before release!");
    111         --readers;
    112         return true;
    113       }
    114 
    115       bool lock() {
    116         if (!mt_only || llvm_is_multithreaded())
    117           return impl.writer_acquire();
    118 
    119         // Single-threaded debugging code.  This would be racy in multithreaded
    120         // mode, but provides not sanity checks in single threaded mode.
    121         assert(writers == 0 && "Writer lock already acquired!");
    122         ++writers;
    123         return true;
    124       }
    125 
    126       bool unlock() {
    127         if (!mt_only || llvm_is_multithreaded())
    128           return impl.writer_release();
    129 
    130         // Single-threaded debugging code.  This would be racy in multithreaded
    131         // mode, but provides not sanity checks in single threaded mode.
    132         assert(writers == 1 && "Writer lock not acquired before release!");
    133         --writers;
    134         return true;
    135       }
    136 
    137     private:
    138       SmartRWMutex(const SmartRWMutex<mt_only> & original);
    139       void operator=(const SmartRWMutex<mt_only> &);
    140     };
    141     typedef SmartRWMutex<false> RWMutex;
    142 
    143     /// ScopedReader - RAII acquisition of a reader lock
    144     template<bool mt_only>
    145     struct SmartScopedReader {
    146       SmartRWMutex<mt_only>& mutex;
    147 
    148       explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
    149         mutex.lock_shared();
    150       }
    151 
    152       ~SmartScopedReader() {
    153         mutex.unlock_shared();
    154       }
    155     };
    156     typedef SmartScopedReader<false> ScopedReader;
    157 
    158     /// ScopedWriter - RAII acquisition of a writer lock
    159     template<bool mt_only>
    160     struct SmartScopedWriter {
    161       SmartRWMutex<mt_only>& mutex;
    162 
    163       explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
    164         mutex.lock();
    165       }
    166 
    167       ~SmartScopedWriter() {
    168         mutex.unlock();
    169       }
    170     };
    171     typedef SmartScopedWriter<false> ScopedWriter;
    172   }
    173 }
    174 
    175 #endif
    176