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