Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/llvm/include/llvm/Support/RWMutex.h
Line
Count
Source (jump to first uncovered line)
1
//===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file declares the llvm::sys::RWMutex class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef LLVM_SUPPORT_RWMUTEX_H
14
#define LLVM_SUPPORT_RWMUTEX_H
15
16
#include "llvm/Config/llvm-config.h"
17
#include "llvm/Support/Threading.h"
18
#include <cassert>
19
#include <mutex>
20
#include <shared_mutex>
21
22
// std::shared_timed_mutex is only availble on macOS 10.12 and later.
23
#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
24
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
25
#define LLVM_USE_RW_MUTEX_IMPL
26
#endif
27
#endif
28
29
namespace llvm {
30
namespace sys {
31
32
#if defined(LLVM_USE_RW_MUTEX_IMPL)
33
/// Platform agnostic RWMutex class.
34
class RWMutexImpl {
35
  /// @name Constructors
36
  /// @{
37
public:
38
  /// Initializes the lock but doesn't acquire it.
39
  /// Default Constructor.
40
  explicit RWMutexImpl();
41
42
  /// @}
43
  /// @name Do Not Implement
44
  /// @{
45
  RWMutexImpl(const RWMutexImpl &original) = delete;
46
  RWMutexImpl &operator=(const RWMutexImpl &) = delete;
47
  /// @}
48
49
  /// Releases and removes the lock
50
  /// Destructor
51
  ~RWMutexImpl();
52
53
  /// @}
54
  /// @name Methods
55
  /// @{
56
public:
57
  /// Attempts to unconditionally acquire the lock in reader mode. If the
58
  /// lock is held by a writer, this method will wait until it can acquire
59
  /// the lock.
60
  /// @returns false if any kind of error occurs, true otherwise.
61
  /// Unconditionally acquire the lock in reader mode.
62
  bool lock_shared();
63
64
  /// Attempts to release the lock in reader mode.
65
  /// @returns false if any kind of error occurs, true otherwise.
66
  /// Unconditionally release the lock in reader mode.
67
  bool unlock_shared();
68
69
  /// Attempts to unconditionally acquire the lock in reader mode. If the
70
  /// lock is held by any readers, this method will wait until it can
71
  /// acquire the lock.
72
  /// @returns false if any kind of error occurs, true otherwise.
73
  /// Unconditionally acquire the lock in writer mode.
74
  bool lock();
75
76
  /// Attempts to release the lock in writer mode.
77
  /// @returns false if any kind of error occurs, true otherwise.
78
  /// Unconditionally release the lock in write mode.
79
  bool unlock();
80
81
  //@}
82
  /// @name Platform Dependent Data
83
  /// @{
84
private:
85
#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
86
  void *data_ = nullptr; ///< We don't know what the data will be
87
#endif
88
};
89
#endif
90
91
/// SmartMutex - An R/W mutex with a compile time constant parameter that
92
/// indicates whether this mutex should become a no-op when we're not
93
/// running in multithreaded mode.
94
template <bool mt_only> class SmartRWMutex {
95
  // shared_mutex (C++17) is more efficient than shared_timed_mutex (C++14)
96
  // on Windows and always available on MSVC.
97
#if defined(_MSC_VER) || __cplusplus > 201402L
98
  std::shared_mutex impl;
99
#else
100
#if !defined(LLVM_USE_RW_MUTEX_IMPL)
101
  std::shared_timed_mutex impl;
102
#else
103
  RWMutexImpl impl;
104
#endif
105
#endif
106
  unsigned readers = 0;
107
  unsigned writers = 0;
108
109
public:
110
0
  bool lock_shared() {
111
0
    if (!mt_only || llvm_is_multithreaded()) {
112
0
      impl.lock_shared();
113
0
      return true;
114
0
    }
115
0
116
0
    // Single-threaded debugging code.  This would be racy in multithreaded
117
0
    // mode, but provides not sanity checks in single threaded mode.
118
0
    ++readers;
119
0
    return true;
120
0
  }
121
122
0
  bool unlock_shared() {
123
0
    if (!mt_only || llvm_is_multithreaded()) {
124
0
      impl.unlock_shared();
125
0
      return true;
126
0
    }
127
0
128
0
    // Single-threaded debugging code.  This would be racy in multithreaded
129
0
    // mode, but provides not sanity checks in single threaded mode.
130
0
    assert(readers > 0 && "Reader lock not acquired before release!");
131
0
    --readers;
132
0
    return true;
133
0
  }
134
135
0
  bool lock() {
136
0
    if (!mt_only || llvm_is_multithreaded()) {
137
0
      impl.lock();
138
0
      return true;
139
0
    }
140
0
141
0
    // Single-threaded debugging code.  This would be racy in multithreaded
142
0
    // mode, but provides not sanity checks in single threaded mode.
143
0
    assert(writers == 0 && "Writer lock already acquired!");
144
0
    ++writers;
145
0
    return true;
146
0
  }
147
148
0
  bool unlock() {
149
0
    if (!mt_only || llvm_is_multithreaded()) {
150
0
      impl.unlock();
151
0
      return true;
152
0
    }
153
0
154
0
    // Single-threaded debugging code.  This would be racy in multithreaded
155
0
    // mode, but provides not sanity checks in single threaded mode.
156
0
    assert(writers == 1 && "Writer lock not acquired before release!");
157
0
    --writers;
158
0
    return true;
159
0
  }
160
};
161
162
typedef SmartRWMutex<false> RWMutex;
163
164
/// ScopedReader - RAII acquisition of a reader lock
165
#if !defined(LLVM_USE_RW_MUTEX_IMPL)
166
template <bool mt_only>
167
using SmartScopedReader = const std::shared_lock<SmartRWMutex<mt_only>>;
168
#else
169
template <bool mt_only> struct SmartScopedReader {
170
  SmartRWMutex<mt_only> &mutex;
171
172
  explicit SmartScopedReader(SmartRWMutex<mt_only> &m) : mutex(m) {
173
    mutex.lock_shared();
174
  }
175
176
  ~SmartScopedReader() { mutex.unlock_shared(); }
177
};
178
#endif
179
typedef SmartScopedReader<false> ScopedReader;
180
181
/// ScopedWriter - RAII acquisition of a writer lock
182
#if !defined(LLVM_USE_RW_MUTEX_IMPL)
183
template <bool mt_only>
184
using SmartScopedWriter = std::lock_guard<SmartRWMutex<mt_only>>;
185
#else
186
template <bool mt_only> struct SmartScopedWriter {
187
  SmartRWMutex<mt_only> &mutex;
188
189
  explicit SmartScopedWriter(SmartRWMutex<mt_only> &m) : mutex(m) {
190
    mutex.lock();
191
  }
192
193
  ~SmartScopedWriter() { mutex.unlock(); }
194
};
195
#endif
196
typedef SmartScopedWriter<false> ScopedWriter;
197
198
} // end namespace sys
199
} // end namespace llvm
200
201
#endif // LLVM_SUPPORT_RWMUTEX_H