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_SYSTEM_RWMUTEX_H
     15 #define LLVM_SYSTEM_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) LLVM_DELETED_FUNCTION;
     80       void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION;
     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 : public RWMutexImpl {
     89       unsigned readers, writers;
     90     public:
     91       explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { }
     92 
     93       bool reader_acquire() {
     94         if (!mt_only || llvm_is_multithreaded())
     95           return RWMutexImpl::reader_acquire();
     96 
     97         // Single-threaded debugging code.  This would be racy in multithreaded
     98         // mode, but provides not sanity checks in single threaded mode.
     99         ++readers;
    100         return true;
    101       }
    102 
    103       bool reader_release() {
    104         if (!mt_only || llvm_is_multithreaded())
    105           return RWMutexImpl::reader_release();
    106 
    107         // Single-threaded debugging code.  This would be racy in multithreaded
    108         // mode, but provides not sanity checks in single threaded mode.
    109         assert(readers > 0 && "Reader lock not acquired before release!");
    110         --readers;
    111         return true;
    112       }
    113 
    114       bool writer_acquire() {
    115         if (!mt_only || llvm_is_multithreaded())
    116           return RWMutexImpl::writer_acquire();
    117 
    118         // Single-threaded debugging code.  This would be racy in multithreaded
    119         // mode, but provides not sanity checks in single threaded mode.
    120         assert(writers == 0 && "Writer lock already acquired!");
    121         ++writers;
    122         return true;
    123       }
    124 
    125       bool writer_release() {
    126         if (!mt_only || llvm_is_multithreaded())
    127           return RWMutexImpl::writer_release();
    128 
    129         // Single-threaded debugging code.  This would be racy in multithreaded
    130         // mode, but provides not sanity checks in single threaded mode.
    131         assert(writers == 1 && "Writer lock not acquired before release!");
    132         --writers;
    133         return true;
    134       }
    135 
    136     private:
    137       SmartRWMutex(const SmartRWMutex<mt_only> & original);
    138       void operator=(const SmartRWMutex<mt_only> &);
    139     };
    140     typedef SmartRWMutex<false> RWMutex;
    141 
    142     /// ScopedReader - RAII acquisition of a reader lock
    143     template<bool mt_only>
    144     struct SmartScopedReader {
    145       SmartRWMutex<mt_only>& mutex;
    146 
    147       explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
    148         mutex.reader_acquire();
    149       }
    150 
    151       ~SmartScopedReader() {
    152         mutex.reader_release();
    153       }
    154     };
    155     typedef SmartScopedReader<false> ScopedReader;
    156 
    157     /// ScopedWriter - RAII acquisition of a writer lock
    158     template<bool mt_only>
    159     struct SmartScopedWriter {
    160       SmartRWMutex<mt_only>& mutex;
    161 
    162       explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
    163         mutex.writer_acquire();
    164       }
    165 
    166       ~SmartScopedWriter() {
    167         mutex.writer_release();
    168       }
    169     };
    170     typedef SmartScopedWriter<false> ScopedWriter;
    171   }
    172 }
    173 
    174 #endif
    175