16class QReadWriteLockPrivate;
18class QBasicReadWriteLock
21 constexpr QBasicReadWriteLock() =
default;
25 tryLockForReadInternal(QDeadlineTimer::Forever, 0);
29 return tryLockForReadInternal(QDeadlineTimer(), QtTsan::TryLock);
31 bool tryLockForRead(QDeadlineTimer timeout)
33 return tryLockForReadInternal(timeout, QtTsan::TryLock);
38 tryLockForWriteInternal(QDeadlineTimer::Forever, 0);
40 bool tryLockForWrite()
42 return tryLockForWriteInternal(QDeadlineTimer(), QtTsan::TryLock);
44 bool tryLockForWrite(QDeadlineTimer timeout)
46 return tryLockForWriteInternal(timeout, QtTsan::TryLock);
52 QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
53 quintptr u = quintptr(d);
54 Q_ASSERT_X(u,
"QReadWriteLock::unlock()",
"Cannot unlock an unlocked lock");
55 if (u & StateLockedForRead)
56 flags |= QtTsan::ReadLock;
57#ifdef QT_BUILDING_UNDER_TSAN
58 else if (u > StateMask && isContendedLockForRead(d))
59 flags |= QtTsan::ReadLock;
62 QtTsan::mutexPreUnlock(
this, flags);
63 if (u > StateMask || !d_ptr.testAndSetRelease(d,
nullptr, d))
65 QtTsan::mutexPostUnlock(
this, flags);
69 void lock() { lockForWrite(); }
70 void lock_shared() { lockForRead(); }
71 bool try_lock() {
return tryLockForWrite(); }
72 bool try_lock_shared() {
return tryLockForRead(); }
73 void unlock_shared() { unlock(); }
76 static constexpr quintptr StateLockedForRead = 0x1;
77 static constexpr quintptr StateLockedForWrite = 0x2;
78 static constexpr quintptr StateMask = StateLockedForRead | StateLockedForWrite;
79 static constexpr quintptr Counter = 0x10;
81 Q_ALWAYS_INLINE
bool fastTryLockForRead(QReadWriteLockPrivate *&d)
84 auto dummyValue =
reinterpret_cast<QReadWriteLockPrivate *>(StateLockedForRead);
85 return d_ptr.testAndSetAcquire(
nullptr, dummyValue, d);
86 }
else if (quintptr u = quintptr(d), v = u + Counter; u & StateLockedForRead) {
87 return d_ptr.testAndSetAcquire(d,
reinterpret_cast<QReadWriteLockPrivate *>(v), d);
92 Q_ALWAYS_INLINE
bool tryLockForReadInternal(QDeadlineTimer timeout,
unsigned tsanFlags)
94 tsanFlags |= QtTsan::ReadLock;
95 QtTsan::mutexPreLock(
this, tsanFlags);
97 QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
98 bool locked = fastTryLockForRead(d);
100 locked = contendedTryLockForRead(timeout, d);
103 tsanFlags |= QtTsan::TryLockFailed;
104 QtTsan::mutexPostLock(
this, tsanFlags, 0);
108 Q_ALWAYS_INLINE
bool fastTryLockForWrite(QReadWriteLockPrivate *&d)
110 auto dummyValue =
reinterpret_cast<QReadWriteLockPrivate *>(StateLockedForWrite);
112 return d_ptr.testAndSetAcquire(
nullptr, dummyValue, d);
116 Q_ALWAYS_INLINE
bool tryLockForWriteInternal(QDeadlineTimer timeout,
unsigned tsanFlags)
118 QtTsan::mutexPreLock(
this, tsanFlags);
120 QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
121 bool locked = fastTryLockForWrite(d);
123 locked = contendedTryLockForWrite(timeout, d);
126 tsanFlags |= QtTsan::TryLockFailed;
127 QtTsan::mutexPostLock(
this, tsanFlags, 0);
131 Q_CORE_EXPORT
bool contendedTryLockForRead(QDeadlineTimer timeout,
void *dd);
132 Q_CORE_EXPORT
bool contendedTryLockForWrite(QDeadlineTimer timeout,
void *dd);
133 Q_CORE_EXPORT
void contendedUnlock(
void *dd);
134 Q_CORE_EXPORT
bool isContendedLockForRead(
const void *dd) Q_DECL_PURE_FUNCTION;
136 constexpr QBasicReadWriteLock(QReadWriteLockPrivate *d)
noexcept : d_ptr(d)
138 Q_DISABLE_COPY(QBasicReadWriteLock)
139 QAtomicPointer<QReadWriteLockPrivate> d_ptr = {
nullptr };
140 friend class QReadWriteLockPrivate;
143class QT6_ONLY(Q_CORE_EXPORT) QReadWriteLock :
public QBasicReadWriteLock
146 enum RecursionMode { NonRecursive, Recursive };
148 QT_CORE_INLINE_SINCE(6, 6)
149 explicit QReadWriteLock(RecursionMode recursionMode = NonRecursive);
150 QT_CORE_INLINE_SINCE(6, 6)
153#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
156 bool tryLockForRead();
158 QT_CORE_INLINE_SINCE(6, 6)
159 bool tryLockForRead(
int timeout);
160#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
161 bool tryLockForRead(QDeadlineTimer timeout = {});
163 using QBasicReadWriteLock::tryLockForRead;
165#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
168 bool tryLockForWrite();
170 QT_CORE_INLINE_SINCE(6, 6)
171 bool tryLockForWrite(
int timeout);
172#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
173 bool tryLockForWrite(QDeadlineTimer timeout = {});
175 using QBasicReadWriteLock::tryLockForWrite;
177#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
182 QT7_ONLY(Q_CORE_EXPORT)
183 static QReadWriteLockPrivate *initRecursive();
184 QT7_ONLY(Q_CORE_EXPORT)
185 static void destroyRecursive(QReadWriteLockPrivate *);
188#if QT_CORE_INLINE_IMPL_SINCE(6
, 6
)
189QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
190 : QBasicReadWriteLock(recursionMode == Recursive ? initRecursive() :
nullptr)
194QReadWriteLock::~QReadWriteLock()
196 if (
auto d = d_ptr.loadAcquire())
200bool QReadWriteLock::tryLockForRead(
int timeout)
202 return tryLockForRead(QDeadlineTimer(timeout));
205bool QReadWriteLock::tryLockForWrite(
int timeout)
207 return tryLockForWrite(QDeadlineTimer(timeout));
211#if defined(Q_CC_MSVC)
212#pragma warning( push )
213#pragma warning( disable : 4312
)
216class QT6_ONLY(Q_CORE_EXPORT) QReadLocker
220 inline QReadLocker(QReadWriteLock *readWriteLock);
222 inline ~QReadLocker()
228 if ((q_val & quintptr(1u)) == quintptr(1u)) {
229 q_val &= ~quintptr(1u);
230 readWriteLock()->unlock();
238 if ((q_val & quintptr(1u)) == quintptr(0u)) {
239 readWriteLock()->lockForRead();
240 q_val |= quintptr(1u);
245 inline QReadWriteLock *readWriteLock()
const
246 {
return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
249 Q_DISABLE_COPY(QReadLocker)
253inline QReadLocker::QReadLocker(QReadWriteLock *areadWriteLock)
254 : q_val(
reinterpret_cast<quintptr>(areadWriteLock))
256 Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
257 "QReadLocker",
"QReadWriteLock pointer is misaligned");
261class QT6_ONLY(Q_CORE_EXPORT) QWriteLocker
265 inline QWriteLocker(QReadWriteLock *readWriteLock);
267 inline ~QWriteLocker()
273 if ((q_val & quintptr(1u)) == quintptr(1u)) {
274 q_val &= ~quintptr(1u);
275 readWriteLock()->unlock();
283 if ((q_val & quintptr(1u)) == quintptr(0u)) {
284 readWriteLock()->lockForWrite();
285 q_val |= quintptr(1u);
290 inline QReadWriteLock *readWriteLock()
const
291 {
return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
295 Q_DISABLE_COPY(QWriteLocker)
299inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock)
300 : q_val(
reinterpret_cast<quintptr>(areadWriteLock))
302 Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
303 "QWriteLocker",
"QReadWriteLock pointer is misaligned");
307#if defined(Q_CC_MSVC)
308#pragma warning( pop )
313class QT6_ONLY(Q_CORE_EXPORT) QReadWriteLock
316 enum RecursionMode { NonRecursive, Recursive };
317 inline explicit QReadWriteLock(RecursionMode = NonRecursive)
noexcept { }
318 inline ~QReadWriteLock() { }
320 void lockForRead()
noexcept { }
321 bool tryLockForRead()
noexcept {
return true; }
322 bool tryLockForRead(QDeadlineTimer)
noexcept {
return true; }
323 bool tryLockForRead(
int timeout)
noexcept { Q_UNUSED(timeout);
return true; }
325 void lockForWrite()
noexcept { }
326 bool tryLockForWrite()
noexcept {
return true; }
327 bool tryLockForWrite(QDeadlineTimer)
noexcept {
return true; }
328 bool tryLockForWrite(
int timeout)
noexcept { Q_UNUSED(timeout);
return true; }
330 void unlock()
noexcept { }
333 Q_DISABLE_COPY(QReadWriteLock)