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 #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
     74       void* data_; ///< We don't know what the data will be
     75 #endif
     76 
     77     /// @}
     78     /// @name Do Not Implement
     79     /// @{
     80     private:
     81       RWMutexImpl(const RWMutexImpl & original) = delete;
     82       void operator=(const RWMutexImpl &) = delete;
     83     /// @}
     84     };
     85 
     86     /// SmartMutex - An R/W mutex with a compile time constant parameter that
     87     /// indicates whether this mutex should become a no-op when we're not
     88     /// running in multithreaded mode.
     89     template<bool mt_only>
     90     class SmartRWMutex {
     91       RWMutexImpl impl;
     92       unsigned readers, writers;
     93     public:
     94       explicit SmartRWMutex() : impl(), readers(0), writers(0) { }
     95 
     96       bool lock_shared() {
     97         if (!mt_only || llvm_is_multithreaded())
     98           return impl.reader_acquire();
     99 
    100         // Single-threaded debugging code.  This would be racy in multithreaded
    101         // mode, but provides not sanity checks in single threaded mode.
    102         ++readers;
    103         return true;
    104       }
    105 
    106       bool unlock_shared() {
    107         if (!mt_only || llvm_is_multithreaded())
    108           return impl.reader_release();
    109 
    110         // Single-threaded debugging code.  This would be racy in multithreaded
    111         // mode, but provides not sanity checks in single threaded mode.
    112         assert(readers > 0 && "Reader lock not acquired before release!");
    113         --readers;
    114         return true;
    115       }
    116 
    117       bool lock() {
    118         if (!mt_only || llvm_is_multithreaded())
    119           return impl.writer_acquire();
    120 
    121         // Single-threaded debugging code.  This would be racy in multithreaded
    122         // mode, but provides not sanity checks in single threaded mode.
    123         assert(writers == 0 && "Writer lock already acquired!");
    124         ++writers;
    125         return true;
    126       }
    127 
    128       bool unlock() {
    129         if (!mt_only || llvm_is_multithreaded())
    130           return impl.writer_release();
    131 
    132         // Single-threaded debugging code.  This would be racy in multithreaded
    133         // mode, but provides not sanity checks in single threaded mode.
    134         assert(writers == 1 && "Writer lock not acquired before release!");
    135         --writers;
    136         return true;
    137       }
    138 
    139     private:
    140       SmartRWMutex(const SmartRWMutex<mt_only> & original);
    141       void operator=(const SmartRWMutex<mt_only> &);
    142     };
    143     typedef SmartRWMutex<false> RWMutex;
    144 
    145     /// ScopedReader - RAII acquisition of a reader lock
    146     template<bool mt_only>
    147     struct SmartScopedReader {
    148       SmartRWMutex<mt_only>& mutex;
    149 
    150       explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
    151         mutex.lock_shared();
    152       }
    153 
    154       ~SmartScopedReader() {
    155         mutex.unlock_shared();
    156       }
    157     };
    158     typedef SmartScopedReader<false> ScopedReader;
    159 
    160     /// ScopedWriter - RAII acquisition of a writer lock
    161     template<bool mt_only>
    162     struct SmartScopedWriter {
    163       SmartRWMutex<mt_only>& mutex;
    164 
    165       explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
    166         mutex.lock();
    167       }
    168 
    169       ~SmartScopedWriter() {
    170         mutex.unlock();
    171       }
    172     };
    173     typedef SmartScopedWriter<false> ScopedWriter;
    174   }
    175 }
    176 
    177 #endif
    178