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/Config/llvm-config.h"
     18 #include "llvm/Support/Threading.h"
     19 #include <cassert>
     20 
     21 namespace llvm {
     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     /// @}
     36     /// @name Do Not Implement
     37     /// @{
     38       RWMutexImpl(const RWMutexImpl & original) = delete;
     39       RWMutexImpl &operator=(const RWMutexImpl &) = delete;
     40     /// @}
     41 
     42       /// Releases and removes the lock
     43       /// @brief Destructor
     44       ~RWMutexImpl();
     45 
     46     /// @}
     47     /// @name Methods
     48     /// @{
     49     public:
     50 
     51       /// Attempts to unconditionally acquire the lock in reader mode. If the
     52       /// lock is held by a writer, this method will wait until it can acquire
     53       /// the lock.
     54       /// @returns false if any kind of error occurs, true otherwise.
     55       /// @brief Unconditionally acquire the lock in reader mode.
     56       bool reader_acquire();
     57 
     58       /// Attempts to release the lock in reader mode.
     59       /// @returns false if any kind of error occurs, true otherwise.
     60       /// @brief Unconditionally release the lock in reader mode.
     61       bool reader_release();
     62 
     63       /// Attempts to unconditionally acquire the lock in reader mode. If the
     64       /// lock is held by any readers, this method will wait until it can
     65       /// acquire the lock.
     66       /// @returns false if any kind of error occurs, true otherwise.
     67       /// @brief Unconditionally acquire the lock in writer mode.
     68       bool writer_acquire();
     69 
     70       /// Attempts to release the lock in writer mode.
     71       /// @returns false if any kind of error occurs, true otherwise.
     72       /// @brief Unconditionally release the lock in write mode.
     73       bool writer_release();
     74 
     75     //@}
     76     /// @name Platform Dependent Data
     77     /// @{
     78     private:
     79 #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
     80       void* data_ = nullptr; ///< We don't know what the data will be
     81 #endif
     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 = 0;
     91       unsigned writers = 0;
     92 
     93     public:
     94       explicit SmartRWMutex() = default;
     95       SmartRWMutex(const SmartRWMutex<mt_only> & original) = delete;
     96       SmartRWMutex<mt_only> &operator=(const SmartRWMutex<mt_only> &) = delete;
     97 
     98       bool lock_shared() {
     99         if (!mt_only || llvm_is_multithreaded())
    100           return impl.reader_acquire();
    101 
    102         // Single-threaded debugging code.  This would be racy in multithreaded
    103         // mode, but provides not sanity checks in single threaded mode.
    104         ++readers;
    105         return true;
    106       }
    107 
    108       bool unlock_shared() {
    109         if (!mt_only || llvm_is_multithreaded())
    110           return impl.reader_release();
    111 
    112         // Single-threaded debugging code.  This would be racy in multithreaded
    113         // mode, but provides not sanity checks in single threaded mode.
    114         assert(readers > 0 && "Reader lock not acquired before release!");
    115         --readers;
    116         return true;
    117       }
    118 
    119       bool lock() {
    120         if (!mt_only || llvm_is_multithreaded())
    121           return impl.writer_acquire();
    122 
    123         // Single-threaded debugging code.  This would be racy in multithreaded
    124         // mode, but provides not sanity checks in single threaded mode.
    125         assert(writers == 0 && "Writer lock already acquired!");
    126         ++writers;
    127         return true;
    128       }
    129 
    130       bool unlock() {
    131         if (!mt_only || llvm_is_multithreaded())
    132           return impl.writer_release();
    133 
    134         // Single-threaded debugging code.  This would be racy in multithreaded
    135         // mode, but provides not sanity checks in single threaded mode.
    136         assert(writers == 1 && "Writer lock not acquired before release!");
    137         --writers;
    138         return true;
    139       }
    140     };
    141 
    142     typedef SmartRWMutex<false> RWMutex;
    143 
    144     /// ScopedReader - RAII acquisition of a reader lock
    145     template<bool mt_only>
    146     struct SmartScopedReader {
    147       SmartRWMutex<mt_only>& mutex;
    148 
    149       explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
    150         mutex.lock_shared();
    151       }
    152 
    153       ~SmartScopedReader() {
    154         mutex.unlock_shared();
    155       }
    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 
    174     typedef SmartScopedWriter<false> ScopedWriter;
    175 
    176 } // end namespace sys
    177 } // end namespace llvm
    178 
    179 #endif // LLVM_SUPPORT_RWMUTEX_H
    180