RWMutex.h revision 218885
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
20namespace 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