1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QREADWRITELOCK_H
6#define QREADWRITELOCK_H
7
8#include <QtCore/qglobal.h>
9#include <QtCore/qdeadlinetimer.h>
10
11QT_BEGIN_NAMESPACE
12
13#if QT_CONFIG(thread)
14
15class QReadWriteLockPrivate;
16
17class Q_CORE_EXPORT QReadWriteLock
18{
19public:
20 enum RecursionMode { NonRecursive, Recursive };
21
22 QT_CORE_INLINE_SINCE(6, 6)
23 explicit QReadWriteLock(RecursionMode recursionMode = NonRecursive);
24 QT_CORE_INLINE_SINCE(6, 6)
25 ~QReadWriteLock();
26
27 QT_CORE_INLINE_SINCE(6, 6)
28 void lockForRead();
29#if QT_CORE_REMOVED_SINCE(6, 6)
30 bool tryLockForRead();
31#endif
32 QT_CORE_INLINE_SINCE(6, 6)
33 bool tryLockForRead(int timeout);
34 bool tryLockForRead(QDeadlineTimer timeout = {});
35
36 QT_CORE_INLINE_SINCE(6, 6)
37 void lockForWrite();
38#if QT_CORE_REMOVED_SINCE(6, 6)
39 bool tryLockForWrite();
40#endif
41 QT_CORE_INLINE_SINCE(6, 6)
42 bool tryLockForWrite(int timeout);
43 bool tryLockForWrite(QDeadlineTimer timeout = {});
44
45 void unlock();
46
47private:
48 Q_DISABLE_COPY(QReadWriteLock)
49 QAtomicPointer<QReadWriteLockPrivate> d_ptr;
50 friend class QReadWriteLockPrivate;
51 static QReadWriteLockPrivate *initRecursive();
52 static void destroyRecursive(QReadWriteLockPrivate *);
53};
54
55#if QT_CORE_INLINE_IMPL_SINCE(6, 6)
56QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
57 : d_ptr(recursionMode == Recursive ? initRecursive() : nullptr)
58{
59}
60
61QReadWriteLock::~QReadWriteLock()
62{
63 if (auto d = d_ptr.loadAcquire())
64 destroyRecursive(d);
65}
66
67void QReadWriteLock::lockForRead()
68{
69 tryLockForRead(timeout: QDeadlineTimer(QDeadlineTimer::Forever));
70}
71
72bool QReadWriteLock::tryLockForRead(int timeout)
73{
74 return tryLockForRead(timeout: QDeadlineTimer(timeout));
75}
76
77void QReadWriteLock::lockForWrite()
78{
79 tryLockForWrite(timeout: QDeadlineTimer(QDeadlineTimer::Forever));
80}
81
82bool QReadWriteLock::tryLockForWrite(int timeout)
83{
84 return tryLockForWrite(timeout: QDeadlineTimer(timeout));
85}
86#endif // inline since 6.6
87
88#if defined(Q_CC_MSVC)
89#pragma warning( push )
90#pragma warning( disable : 4312 ) // ignoring the warning from /Wp64
91#endif
92
93class QT6_ONLY(Q_CORE_EXPORT) QReadLocker
94{
95public:
96 Q_NODISCARD_CTOR
97 inline QReadLocker(QReadWriteLock *readWriteLock);
98
99 inline ~QReadLocker()
100 { unlock(); }
101
102 inline void unlock()
103 {
104 if (q_val) {
105 if ((q_val & quintptr(1u)) == quintptr(1u)) {
106 q_val &= ~quintptr(1u);
107 readWriteLock()->unlock();
108 }
109 }
110 }
111
112 inline void relock()
113 {
114 if (q_val) {
115 if ((q_val & quintptr(1u)) == quintptr(0u)) {
116 readWriteLock()->lockForRead();
117 q_val |= quintptr(1u);
118 }
119 }
120 }
121
122 inline QReadWriteLock *readWriteLock() const
123 { return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
124
125private:
126 Q_DISABLE_COPY(QReadLocker)
127 quintptr q_val;
128};
129
130inline QReadLocker::QReadLocker(QReadWriteLock *areadWriteLock)
131 : q_val(reinterpret_cast<quintptr>(areadWriteLock))
132{
133 Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
134 "QReadLocker", "QReadWriteLock pointer is misaligned");
135 relock();
136}
137
138class QT6_ONLY(Q_CORE_EXPORT) QWriteLocker
139{
140public:
141 Q_NODISCARD_CTOR
142 inline QWriteLocker(QReadWriteLock *readWriteLock);
143
144 inline ~QWriteLocker()
145 { unlock(); }
146
147 inline void unlock()
148 {
149 if (q_val) {
150 if ((q_val & quintptr(1u)) == quintptr(1u)) {
151 q_val &= ~quintptr(1u);
152 readWriteLock()->unlock();
153 }
154 }
155 }
156
157 inline void relock()
158 {
159 if (q_val) {
160 if ((q_val & quintptr(1u)) == quintptr(0u)) {
161 readWriteLock()->lockForWrite();
162 q_val |= quintptr(1u);
163 }
164 }
165 }
166
167 inline QReadWriteLock *readWriteLock() const
168 { return reinterpret_cast<QReadWriteLock *>(q_val & ~quintptr(1u)); }
169
170
171private:
172 Q_DISABLE_COPY(QWriteLocker)
173 quintptr q_val;
174};
175
176inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock)
177 : q_val(reinterpret_cast<quintptr>(areadWriteLock))
178{
179 Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0),
180 "QWriteLocker", "QReadWriteLock pointer is misaligned");
181 relock();
182}
183
184#if defined(Q_CC_MSVC)
185#pragma warning( pop )
186#endif
187
188#else // QT_CONFIG(thread)
189
190class QT6_ONLY(Q_CORE_EXPORT) QReadWriteLock
191{
192public:
193 enum RecursionMode { NonRecursive, Recursive };
194 inline explicit QReadWriteLock(RecursionMode = NonRecursive) noexcept { }
195 inline ~QReadWriteLock() { }
196
197 void lockForRead() noexcept { }
198 bool tryLockForRead() noexcept { return true; }
199 bool tryLockForRead(QDeadlineTimer) noexcept { return true; }
200 bool tryLockForRead(int timeout) noexcept { Q_UNUSED(timeout); return true; }
201
202 void lockForWrite() noexcept { }
203 bool tryLockForWrite() noexcept { return true; }
204 bool tryLockForWrite(QDeadlineTimer) noexcept { return true; }
205 bool tryLockForWrite(int timeout) noexcept { Q_UNUSED(timeout); return true; }
206
207 void unlock() noexcept { }
208
209private:
210 Q_DISABLE_COPY(QReadWriteLock)
211};
212
213class QT6_ONLY(Q_CORE_EXPORT) QReadLocker
214{
215public:
216 Q_NODISCARD_CTOR
217 inline explicit QReadLocker(QReadWriteLock *) noexcept { }
218 inline ~QReadLocker() noexcept { }
219
220 void unlock() noexcept { }
221 void relock() noexcept { }
222 QReadWriteLock *readWriteLock() noexcept { return nullptr; }
223
224private:
225 Q_DISABLE_COPY(QReadLocker)
226};
227
228class QT6_ONLY(Q_CORE_EXPORT) QWriteLocker
229{
230public:
231 Q_NODISCARD_CTOR
232 inline explicit QWriteLocker(QReadWriteLock *) noexcept { }
233 inline ~QWriteLocker() noexcept { }
234
235 void unlock() noexcept { }
236 void relock() noexcept { }
237 QReadWriteLock *readWriteLock() noexcept { return nullptr; }
238
239private:
240 Q_DISABLE_COPY(QWriteLocker)
241};
242
243#endif // QT_CONFIG(thread)
244
245QT_END_NAMESPACE
246
247#endif // QREADWRITELOCK_H
248

source code of qtbase/src/corelib/thread/qreadwritelock.h