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