1218885Sdim//===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file declares the llvm::sys::RWMutex class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim#ifndef LLVM_SYSTEM_RWMUTEX_H 15218885Sdim#define LLVM_SYSTEM_RWMUTEX_H 16218885Sdim 17245431Sdim#include "llvm/Support/Compiler.h" 18218885Sdim#include "llvm/Support/Threading.h" 19218885Sdim#include <cassert> 20218885Sdim 21218885Sdimnamespace llvm 22218885Sdim{ 23218885Sdim namespace sys 24218885Sdim { 25218885Sdim /// @brief Platform agnostic RWMutex class. 26218885Sdim class RWMutexImpl 27218885Sdim { 28218885Sdim /// @name Constructors 29218885Sdim /// @{ 30218885Sdim public: 31218885Sdim 32218885Sdim /// Initializes the lock but doesn't acquire it. 33218885Sdim /// @brief Default Constructor. 34218885Sdim explicit RWMutexImpl(); 35218885Sdim 36218885Sdim /// Releases and removes the lock 37218885Sdim /// @brief Destructor 38218885Sdim ~RWMutexImpl(); 39218885Sdim 40218885Sdim /// @} 41218885Sdim /// @name Methods 42218885Sdim /// @{ 43218885Sdim public: 44218885Sdim 45218885Sdim /// Attempts to unconditionally acquire the lock in reader mode. If the 46218885Sdim /// lock is held by a writer, this method will wait until it can acquire 47218885Sdim /// the lock. 48218885Sdim /// @returns false if any kind of error occurs, true otherwise. 49218885Sdim /// @brief Unconditionally acquire the lock in reader mode. 50218885Sdim bool reader_acquire(); 51218885Sdim 52218885Sdim /// Attempts to release the lock in reader mode. 53218885Sdim /// @returns false if any kind of error occurs, true otherwise. 54218885Sdim /// @brief Unconditionally release the lock in reader mode. 55218885Sdim bool reader_release(); 56218885Sdim 57218885Sdim /// Attempts to unconditionally acquire the lock in reader mode. If the 58218885Sdim /// lock is held by any readers, this method will wait until it can 59218885Sdim /// acquire the lock. 60218885Sdim /// @returns false if any kind of error occurs, true otherwise. 61218885Sdim /// @brief Unconditionally acquire the lock in writer mode. 62218885Sdim bool writer_acquire(); 63218885Sdim 64218885Sdim /// Attempts to release the lock in writer mode. 65218885Sdim /// @returns false if any kind of error occurs, true otherwise. 66218885Sdim /// @brief Unconditionally release the lock in write mode. 67218885Sdim bool writer_release(); 68218885Sdim 69218885Sdim //@} 70218885Sdim /// @name Platform Dependent Data 71218885Sdim /// @{ 72218885Sdim private: 73218885Sdim void* data_; ///< We don't know what the data will be 74218885Sdim 75218885Sdim /// @} 76218885Sdim /// @name Do Not Implement 77218885Sdim /// @{ 78218885Sdim private: 79245431Sdim RWMutexImpl(const RWMutexImpl & original) LLVM_DELETED_FUNCTION; 80245431Sdim void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION; 81218885Sdim /// @} 82218885Sdim }; 83218885Sdim 84218885Sdim /// SmartMutex - An R/W mutex with a compile time constant parameter that 85218885Sdim /// indicates whether this mutex should become a no-op when we're not 86218885Sdim /// running in multithreaded mode. 87218885Sdim template<bool mt_only> 88218885Sdim class SmartRWMutex : public RWMutexImpl { 89218885Sdim unsigned readers, writers; 90218885Sdim public: 91218885Sdim explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { } 92218885Sdim 93218885Sdim bool reader_acquire() { 94218885Sdim if (!mt_only || llvm_is_multithreaded()) 95218885Sdim return RWMutexImpl::reader_acquire(); 96218885Sdim 97218885Sdim // Single-threaded debugging code. This would be racy in multithreaded 98218885Sdim // mode, but provides not sanity checks in single threaded mode. 99218885Sdim ++readers; 100218885Sdim return true; 101218885Sdim } 102218885Sdim 103218885Sdim bool reader_release() { 104218885Sdim if (!mt_only || llvm_is_multithreaded()) 105218885Sdim return RWMutexImpl::reader_release(); 106218885Sdim 107218885Sdim // Single-threaded debugging code. This would be racy in multithreaded 108218885Sdim // mode, but provides not sanity checks in single threaded mode. 109218885Sdim assert(readers > 0 && "Reader lock not acquired before release!"); 110218885Sdim --readers; 111218885Sdim return true; 112218885Sdim } 113218885Sdim 114218885Sdim bool writer_acquire() { 115218885Sdim if (!mt_only || llvm_is_multithreaded()) 116218885Sdim return RWMutexImpl::writer_acquire(); 117218885Sdim 118218885Sdim // Single-threaded debugging code. This would be racy in multithreaded 119218885Sdim // mode, but provides not sanity checks in single threaded mode. 120218885Sdim assert(writers == 0 && "Writer lock already acquired!"); 121218885Sdim ++writers; 122218885Sdim return true; 123218885Sdim } 124218885Sdim 125218885Sdim bool writer_release() { 126218885Sdim if (!mt_only || llvm_is_multithreaded()) 127218885Sdim return RWMutexImpl::writer_release(); 128218885Sdim 129218885Sdim // Single-threaded debugging code. This would be racy in multithreaded 130218885Sdim // mode, but provides not sanity checks in single threaded mode. 131218885Sdim assert(writers == 1 && "Writer lock not acquired before release!"); 132218885Sdim --writers; 133218885Sdim return true; 134218885Sdim } 135218885Sdim 136218885Sdim private: 137218885Sdim SmartRWMutex(const SmartRWMutex<mt_only> & original); 138218885Sdim void operator=(const SmartRWMutex<mt_only> &); 139218885Sdim }; 140218885Sdim typedef SmartRWMutex<false> RWMutex; 141218885Sdim 142218885Sdim /// ScopedReader - RAII acquisition of a reader lock 143218885Sdim template<bool mt_only> 144218885Sdim struct SmartScopedReader { 145218885Sdim SmartRWMutex<mt_only>& mutex; 146218885Sdim 147218885Sdim explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) { 148218885Sdim mutex.reader_acquire(); 149218885Sdim } 150218885Sdim 151218885Sdim ~SmartScopedReader() { 152218885Sdim mutex.reader_release(); 153218885Sdim } 154218885Sdim }; 155218885Sdim typedef SmartScopedReader<false> ScopedReader; 156218885Sdim 157218885Sdim /// ScopedWriter - RAII acquisition of a writer lock 158218885Sdim template<bool mt_only> 159218885Sdim struct SmartScopedWriter { 160218885Sdim SmartRWMutex<mt_only>& mutex; 161218885Sdim 162218885Sdim explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) { 163218885Sdim mutex.writer_acquire(); 164218885Sdim } 165218885Sdim 166218885Sdim ~SmartScopedWriter() { 167218885Sdim mutex.writer_release(); 168218885Sdim } 169218885Sdim }; 170218885Sdim typedef SmartScopedWriter<false> ScopedWriter; 171218885Sdim } 172218885Sdim} 173218885Sdim 174218885Sdim#endif 175