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 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 static QReadWriteLockPrivate *initRecursive();
178 static void destroyRecursive(QReadWriteLockPrivate *);
181#if QT_CORE_INLINE_IMPL_SINCE(6
, 6
)
182QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
183 : QBasicReadWriteLock(recursionMode == Recursive ? initRecursive() :
nullptr)
187QReadWriteLock::~QReadWriteLock()
189 if (
auto d = d_ptr.loadAcquire())
193bool QReadWriteLock::tryLockForRead(
int timeout)
195 return tryLockForRead(QDeadlineTimer(timeout));
198bool QReadWriteLock::tryLockForWrite(
int timeout)
200 return tryLockForWrite(QDeadlineTimer(timeout));
204#if defined(Q_CC_MSVC)
205#pragma warning( push )
206#pragma warning( disable : 4312
)
209class QT6_ONLY(Q_CORE_EXPORT) QReadLocker
213 inline QReadLocker(QReadWriteLock *readWriteLock);
215 inline ~QReadLocker()
221 if ((q_val & quintptr(1u)) == quintptr(1u)) {
222 q_val &= ~quintptr(1u);
223 readWriteLock()->unlock();
231 if ((q_val & quintptr(1u)) == quintptr(0u)) {
232 readWriteLock()->lockForRead();
233 q_val |= quintptr(1u);
238 inline QReadWriteLock *readWriteLock()
const
239 {
return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
242 Q_DISABLE_COPY(QReadLocker)
246inline QReadLocker::QReadLocker(QReadWriteLock *areadWriteLock)
247 : q_val(
reinterpret_cast<quintptr>(areadWriteLock))
249 Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
250 "QReadLocker",
"QReadWriteLock pointer is misaligned");
254class QT6_ONLY(Q_CORE_EXPORT) QWriteLocker
258 inline QWriteLocker(QReadWriteLock *readWriteLock);
260 inline ~QWriteLocker()
266 if ((q_val & quintptr(1u)) == quintptr(1u)) {
267 q_val &= ~quintptr(1u);
268 readWriteLock()->unlock();
276 if ((q_val & quintptr(1u)) == quintptr(0u)) {
277 readWriteLock()->lockForWrite();
278 q_val |= quintptr(1u);
283 inline QReadWriteLock *readWriteLock()
const
284 {
return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
288 Q_DISABLE_COPY(QWriteLocker)
292inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock)
293 : q_val(
reinterpret_cast<quintptr>(areadWriteLock))
295 Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
296 "QWriteLocker",
"QReadWriteLock pointer is misaligned");
300#if defined(Q_CC_MSVC)
301#pragma warning( pop )
306class QT6_ONLY(Q_CORE_EXPORT) QReadWriteLock
309 enum RecursionMode { NonRecursive, Recursive };
310 inline explicit QReadWriteLock(RecursionMode = NonRecursive)
noexcept { }
311 inline ~QReadWriteLock() { }
313 void lockForRead()
noexcept { }
314 bool tryLockForRead()
noexcept {
return true; }
315 bool tryLockForRead(QDeadlineTimer)
noexcept {
return true; }
316 bool tryLockForRead(
int timeout)
noexcept { Q_UNUSED(timeout);
return true; }
318 void lockForWrite()
noexcept { }
319 bool tryLockForWrite()
noexcept {
return true; }
320 bool tryLockForWrite(QDeadlineTimer)
noexcept {
return true; }
321 bool tryLockForWrite(
int timeout)
noexcept { Q_UNUSED(timeout);
return true; }
323 void unlock()
noexcept { }
326 Q_DISABLE_COPY(QReadWriteLock)