Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qreadwritelock_p.h
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
3
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
// Qt-Security score:significant reason:default
5
6
#
ifndef
QREADWRITELOCK_P_H
7
#
define
QREADWRITELOCK_P_H
8
9
//
10
// W A R N I N G
11
// -------------
12
//
13
// This file is not part of the Qt API. It exists for the convenience
14
// of the implementation. This header file may change from version to
15
// version without notice, or even be removed.
16
//
17
// We mean it.
18
//
19
20
#
include
<
QtCore
/
private
/
qlocking_p
.
h
>
21
#
include
<
QtCore
/
private
/
qwaitcondition_p
.
h
>
22
#
include
<
QtCore
/
qreadwritelock
.
h
>
23
#
include
<
QtCore
/
qvarlengtharray
.
h
>
24
25
QT_REQUIRE_CONFIG
(
thread
);
26
27
QT_BEGIN_NAMESPACE
28
29
class
QReadWriteLockPrivate
30
{
31
public
:
32
// export the State constants protected in QReadWriteLock
33
static
constexpr
quintptr StateLockedForRead = QReadWriteLock::StateLockedForRead;
34
static
constexpr
quintptr StateLockedForWrite = QReadWriteLock::StateLockedForWrite;
35
static
constexpr
quintptr StateMask = QReadWriteLock::StateMask;
36
static
constexpr
quintptr MultiplyLocked = QReadWriteLock::Counter;
37
static
constexpr
quintptr IsRecursiveLock = MultiplyLocked << 1;
38
static
constexpr
quintptr RecursivelyLockedForWrite =
39
StateLockedForWrite | MultiplyLocked | IsRecursiveLock;
40
41
explicit
QReadWriteLockPrivate(
bool
isRecursive =
false
)
42
: recursive(isRecursive) {}
43
44
alignas
(QtPrivate::IdealMutexAlignment) std::condition_variable writerCond;
45
std::condition_variable readerCond;
46
47
alignas
(QtPrivate::IdealMutexAlignment) std::mutex mutex;
48
int
readerCount = 0;
49
int
writerCount = 0;
50
int
waitingReaders = 0;
51
int
waitingWriters = 0;
52
const
bool
recursive;
53
54
//Called with the mutex locked
55
bool
lockForWrite(std::unique_lock<std::mutex> &lock, QDeadlineTimer timeout);
56
bool
lockForRead(std::unique_lock<std::mutex> &lock, QDeadlineTimer timeout);
57
void
unlock();
58
59
//memory management
60
int
id = 0;
61
void
release();
62
static
QReadWriteLockPrivate *allocate();
63
64
// Recursive mutex handling
65
Qt::HANDLE currentWriter = {};
66
67
struct
Reader {
68
Qt::HANDLE handle;
69
int
recursionLevel;
70
};
71
72
QVarLengthArray<Reader, 16> currentReaders;
73
74
// called with the mutex unlocked
75
bool
recursiveLockForWrite(QDeadlineTimer timeout);
76
bool
recursiveLockForRead(QDeadlineTimer timeout);
77
void
recursiveUnlock();
78
79
/*!
80
* \internal
81
* Describes the state of the QReadWriteLock whose private is \a dd.
82
*
83
* Returns one of:
84
* \list
85
* \li 0 (unlocked)
86
* \li \c IsRecursiveLock (still unlocked)
87
* \li \c StateLockedForRead
88
* \li \c{StateLockedForRead | IsRecursiveLock}
89
* \li \c StateLockedForWrite
90
* \li \c{StateLockedForWrite | IsRecursiveLock}
91
* \li \c{StateLockedForWrite | IsRecursiveLock | MultiplyLocked} = \c RecursivelyLockedForWrite
92
* \endlist
93
*/
94
static
quintptr describeState(
void
*dd)
noexcept
95
{
96
quintptr u = quintptr(dd);
97
if
(quintptr state = u & StateMask) {
98
// Not a pointer: a non-recursive, uncontended lock. The upper bits
99
// may hold a reader count, which we don't report.
100
return
state;
101
}
102
if
(!u)
103
return
0;
// unlocked
104
105
auto
d =
static_cast
<QReadWriteLockPrivate *>(dd);
106
const
auto
lock = qt_scoped_lock(d->mutex);
107
u = 0;
108
if
(d->writerCount)
109
u |= StateLockedForWrite;
110
else
if
(d->readerCount)
111
u |= StateLockedForRead;
112
if
(d->recursive) {
113
u |= IsRecursiveLock;
114
if
(d->writerCount > 1) {
115
u |= MultiplyLocked;
116
Q_ASSERT(u == RecursivelyLockedForWrite);
117
}
118
}
else
{
119
// non-recursive, quick check of the state
120
Q_ASSERT(d->writerCount <= 1);
121
}
122
return
u;
123
}
124
125
// used by QWaitCondition::wait
126
template
<
typename
Prep,
typename
DoWait>
127
static
bool
waitConditionWait(QReadWriteLock *readWriteLock, Prep &&prep, DoWait &&doWait);
128
};
129
Q_DECLARE_TYPEINFO
(QReadWriteLockPrivate::Reader,
Q_PRIMITIVE_TYPE
);
130
131
template
<
typename
Prep,
typename
DoWait>
132
inline
bool
QReadWriteLockPrivate::waitConditionWait(QReadWriteLock *readWriteLock, Prep &&prep, DoWait &&doWait)
133
{
134
if
(!readWriteLock)
135
return
false
;
136
auto
previousState = describeState(readWriteLock->d_ptr.loadAcquire());
137
if
(previousState == 0)
// unlocked
138
return
false
;
139
if
(previousState == RecursivelyLockedForWrite) {
140
qWarning(
"QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()"
);
141
return
false
;
142
}
143
144
prep();
145
readWriteLock->unlock();
146
bool
returnValue = doWait();
147
148
// relock
149
if
(previousState & StateLockedForWrite)
150
readWriteLock->lockForWrite();
151
else
152
readWriteLock->lockForRead();
153
154
return
returnValue;
155
}
156
157
QT_END_NAMESPACE
158
159
#
endif
// QREADWRITELOCK_P_H
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
QT_REQUIRE_CONFIG
QT_REQUIRE_CONFIG(liburing)
fastTryLock
static Q_ALWAYS_INLINE bool fastTryLock(QAtomicPointer< QReadWriteLockPrivate > &d_ptr, QReadWriteLockPrivate *dummyValue, QReadWriteLockPrivate *&d)
Definition
qreadwritelock.cpp:168
dummyLockedForRead
static QT_BEGIN_NAMESPACE auto dummyLockedForRead()
Definition
qreadwritelock.cpp:31
isUncontendedLocked
static bool isUncontendedLocked(const QReadWriteLockPrivate *d)
Definition
qreadwritelock.cpp:40
dummyLockedForWrite
static auto dummyLockedForWrite()
Definition
qreadwritelock.cpp:35
handleEquals
static auto handleEquals(Qt::HANDLE handle)
Definition
qreadwritelock.cpp:496
Q_DECLARE_TYPEINFO
Q_DECLARE_TYPEINFO(QReadWriteLockPrivate::Reader, Q_PRIMITIVE_TYPE)
qtbase
src
corelib
thread
qreadwritelock_p.h
Generated on
for Qt by
1.18.0