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;
58 QtTsan::mutexPreUnlock(
this, flags);
59 if (u > StateMask || !d_ptr.testAndSetRelease(d,
nullptr, d))
61 QtTsan::mutexPostUnlock(
this, flags);
65 void lock() { lockForWrite(); }
66 void lock_shared() { lockForRead(); }
67 bool try_lock() {
return tryLockForWrite(); }
68 bool try_lock_shared() {
return tryLockForRead(); }
69 void unlock_shared() { unlock(); }
72 static constexpr quintptr StateLockedForRead = 0x1;
73 static constexpr quintptr StateLockedForWrite = 0x2;
74 static constexpr quintptr StateMask = StateLockedForRead | StateLockedForWrite;
75 static constexpr quintptr Counter = 0x10;
77 Q_ALWAYS_INLINE
bool fastTryLockForRead(QReadWriteLockPrivate *&d)
80 auto dummyValue =
reinterpret_cast<QReadWriteLockPrivate *>(StateLockedForRead);
81 return d_ptr.testAndSetAcquire(
nullptr, dummyValue, d);
82 }
else if (quintptr u = quintptr(d), v = u + Counter; u & StateLockedForRead) {
83 return d_ptr.testAndSetAcquire(d,
reinterpret_cast<QReadWriteLockPrivate *>(v), d);
88 Q_ALWAYS_INLINE
bool tryLockForReadInternal(QDeadlineTimer timeout,
unsigned tsanFlags)
90 tsanFlags |= QtTsan::ReadLock;
91 QtTsan::mutexPreLock(
this, tsanFlags);
93 QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
94 bool locked = fastTryLockForRead(d);
96 locked = contendedTryLockForRead(timeout, d);
99 tsanFlags |= QtTsan::TryLockFailed;
100 QtTsan::mutexPostLock(
this, tsanFlags, 0);
104 Q_ALWAYS_INLINE
bool fastTryLockForWrite(QReadWriteLockPrivate *&d)
106 auto dummyValue =
reinterpret_cast<QReadWriteLockPrivate *>(StateLockedForWrite);
108 return d_ptr.testAndSetAcquire(
nullptr, dummyValue, d);
112 Q_ALWAYS_INLINE
bool tryLockForWriteInternal(QDeadlineTimer timeout,
unsigned tsanFlags)
114 QtTsan::mutexPreLock(
this, tsanFlags);
116 QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
117 bool locked = fastTryLockForWrite(d);
119 locked = contendedTryLockForWrite(timeout, d);
122 tsanFlags |= QtTsan::TryLockFailed;
123 QtTsan::mutexPostLock(
this, tsanFlags, 0);
127 Q_CORE_EXPORT
bool contendedTryLockForRead(QDeadlineTimer timeout,
void *dd);
128 Q_CORE_EXPORT
bool contendedTryLockForWrite(QDeadlineTimer timeout,
void *dd);
129 Q_CORE_EXPORT
void contendedUnlock(
void *dd);
131 constexpr QBasicReadWriteLock(QReadWriteLockPrivate *d)
noexcept : d_ptr(d)
133 Q_DISABLE_COPY(QBasicReadWriteLock)
134 QAtomicPointer<QReadWriteLockPrivate> d_ptr = {
nullptr };
135 friend class QReadWriteLockPrivate;
138class QT6_ONLY(Q_CORE_EXPORT) QReadWriteLock :
public QBasicReadWriteLock
141 enum RecursionMode { NonRecursive, Recursive };
143 QT_CORE_INLINE_SINCE(6, 6)
144 explicit QReadWriteLock(RecursionMode recursionMode = NonRecursive);
145 QT_CORE_INLINE_SINCE(6, 6)
148#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
151 bool tryLockForRead();
153 QT_CORE_INLINE_SINCE(6, 6)
154 bool tryLockForRead(
int timeout);
155#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
156 bool tryLockForRead(QDeadlineTimer timeout = {});
158 using QBasicReadWriteLock::tryLockForRead;
160#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
163 bool tryLockForWrite();
165 QT_CORE_INLINE_SINCE(6, 6)
166 bool tryLockForWrite(
int timeout);
167#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
168 bool tryLockForWrite(QDeadlineTimer timeout = {});
170 using QBasicReadWriteLock::tryLockForWrite;
172#if QT_CORE_REMOVED_SINCE(6
, 11
) || defined(Q_QDOC)
177 QT7_ONLY(Q_CORE_EXPORT)
178 static QReadWriteLockPrivate *initRecursive();
179 QT7_ONLY(Q_CORE_EXPORT)
180 static void destroyRecursive(QReadWriteLockPrivate *);
183#if QT_CORE_INLINE_IMPL_SINCE(6
, 6
)
184QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
185 : QBasicReadWriteLock(recursionMode == Recursive ? initRecursive() :
nullptr)
189QReadWriteLock::~QReadWriteLock()
191 if (
auto d = d_ptr.loadAcquire())
195bool QReadWriteLock::tryLockForRead(
int timeout)
197 return tryLockForRead(QDeadlineTimer(timeout));
200bool QReadWriteLock::tryLockForWrite(
int timeout)
202 return tryLockForWrite(QDeadlineTimer(timeout));
206#if defined(Q_CC_MSVC)
207#pragma warning( push )
208#pragma warning( disable : 4312
)
211class QT6_ONLY(Q_CORE_EXPORT) QReadLocker
215 inline QReadLocker(QReadWriteLock *readWriteLock);
217 inline ~QReadLocker()
223 if ((q_val & quintptr(1u)) == quintptr(1u)) {
224 q_val &= ~quintptr(1u);
225 readWriteLock()->unlock();
233 if ((q_val & quintptr(1u)) == quintptr(0u)) {
234 readWriteLock()->lockForRead();
235 q_val |= quintptr(1u);
240 inline QReadWriteLock *readWriteLock()
const
241 {
return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
244 Q_DISABLE_COPY(QReadLocker)
248inline QReadLocker::QReadLocker(QReadWriteLock *areadWriteLock)
249 : q_val(
reinterpret_cast<quintptr>(areadWriteLock))
251 Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
252 "QReadLocker",
"QReadWriteLock pointer is misaligned");
256class QT6_ONLY(Q_CORE_EXPORT) QWriteLocker
260 inline QWriteLocker(QReadWriteLock *readWriteLock);
262 inline ~QWriteLocker()
268 if ((q_val & quintptr(1u)) == quintptr(1u)) {
269 q_val &= ~quintptr(1u);
270 readWriteLock()->unlock();
278 if ((q_val & quintptr(1u)) == quintptr(0u)) {
279 readWriteLock()->lockForWrite();
280 q_val |= quintptr(1u);
285 inline QReadWriteLock *readWriteLock()
const
286 {
return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
290 Q_DISABLE_COPY(QWriteLocker)
294inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock)
295 : q_val(
reinterpret_cast<quintptr>(areadWriteLock))
297 Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
298 "QWriteLocker",
"QReadWriteLock pointer is misaligned");
302#if defined(Q_CC_MSVC)
303#pragma warning( pop )
308class QT6_ONLY(Q_CORE_EXPORT) QReadWriteLock
311 enum RecursionMode { NonRecursive, Recursive };
312 inline explicit QReadWriteLock(RecursionMode = NonRecursive)
noexcept { }
313 inline ~QReadWriteLock() { }
315 void lockForRead()
noexcept { }
316 bool tryLockForRead()
noexcept {
return true; }
317 bool tryLockForRead(QDeadlineTimer)
noexcept {
return true; }
318 bool tryLockForRead(
int timeout)
noexcept { Q_UNUSED(timeout);
return true; }
320 void lockForWrite()
noexcept { }
321 bool tryLockForWrite()
noexcept {
return true; }
322 bool tryLockForWrite(QDeadlineTimer)
noexcept {
return true; }
323 bool tryLockForWrite(
int timeout)
noexcept { Q_UNUSED(timeout);
return true; }
325 void unlock()
noexcept { }
328 Q_DISABLE_COPY(QReadWriteLock)