Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmutex.h
Go to the documentation of this file.
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
4#ifndef QMUTEX_H
5#define QMUTEX_H
6
7#include <QtCore/qglobal.h>
8#include <QtCore/qatomic.h>
9#include <QtCore/qdeadlinetimer.h>
10#include <QtCore/qtsan_impl.h>
11
12#include <chrono>
13
15
16#if QT_CONFIG(thread) || defined(Q_QDOC)
17
18class QMutex;
19class QRecursiveMutex;
20class QMutexPrivate;
21
22class Q_CORE_EXPORT QBasicMutex
23{
24 Q_DISABLE_COPY_MOVE(QBasicMutex)
25protected:
26 static constexpr bool FutexAlwaysAvailable =
27#if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) || defined(Q_OS_WIN) // these platforms use futex
28 true
29#else
30 false
31#endif
32 ;
33
34public:
35 constexpr QBasicMutex()
36 : d_ptr(nullptr)
37 {}
38
39 // BasicLockable concept
40 inline void lock() noexcept(FutexAlwaysAvailable) {
41 QtTsan::mutexPreLock(this, 0u);
42
43 if (!fastTryLock())
44 lockInternal();
45
46 QtTsan::mutexPostLock(this, 0u, 0);
47 }
48
49 // BasicLockable concept
50 inline void unlock() noexcept {
51 Q_ASSERT(d_ptr.loadRelaxed()); //mutex must be locked
52
53 QtTsan::mutexPreUnlock(this, 0u);
54
55 if constexpr (FutexAlwaysAvailable) {
56 // we always unlock if we have futexes
57 if (QMutexPrivate *d = d_ptr.fetchAndStoreRelease(nullptr); d != dummyLocked())
58 unlockInternalFutex(d); // was contended
59 } else {
60 // if we don't have futexes, we can only unlock if not contended
61 if (QMutexPrivate *d; !d_ptr.testAndSetRelease(dummyLocked(), nullptr, d))
62 unlockInternal(d); // was contended
63 }
64
65 QtTsan::mutexPostUnlock(this, 0u);
66 }
67
68 bool tryLock() noexcept {
69 unsigned tsanFlags = QtTsan::TryLock;
70 QtTsan::mutexPreLock(this, tsanFlags);
71
72 const bool success = fastTryLock();
73
74 if (!success)
75 tsanFlags |= QtTsan::TryLockFailed;
76 QtTsan::mutexPostLock(this, tsanFlags, 0);
77
78 return success;
79 }
80
81 // Lockable concept
82 bool try_lock() noexcept { return tryLock(); }
83
84private:
85 inline bool fastTryLock() noexcept
86 {
87 if (d_ptr.loadRelaxed() != nullptr)
88 return false;
89 return d_ptr.testAndSetAcquire(nullptr, dummyLocked());
90 }
91
92 void lockInternal() noexcept(FutexAlwaysAvailable);
93 bool lockInternal(QDeadlineTimer timeout) noexcept(FutexAlwaysAvailable);
94#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
95 bool lockInternal(int timeout) noexcept(FutexAlwaysAvailable);
96 void unlockInternal() noexcept;
97#endif
98 void unlockInternalFutex(void *d) noexcept;
99 void unlockInternal(void *d) noexcept;
100#if QT_CORE_REMOVED_SINCE(6, 9)
101 void destroyInternal(QMutexPrivate *d);
102#endif
103 void destroyInternal(void *d);
104
105 QBasicAtomicPointer<QMutexPrivate> d_ptr;
106 static inline QMutexPrivate *dummyLocked() {
107 return reinterpret_cast<QMutexPrivate *>(quintptr(1));
108 }
109
110 friend class QMutex;
111 friend class QMutexPrivate;
112};
113
114class Q_CORE_EXPORT QMutex : public QBasicMutex
115{
116public:
117 constexpr QMutex() = default;
118 ~QMutex()
119 {
120 QMutexPrivate *d = d_ptr.loadRelaxed();
121 if (d)
122 destroyInternal(d);
123 }
124
125#ifdef Q_QDOC
126 inline void lock() noexcept(FutexAlwaysAvailable);
127 inline void unlock() noexcept;
128 bool tryLock() noexcept;
129#endif
130
131 // Lockable concept
132 bool try_lock() noexcept { return tryLock(); }
133
134
135 using QBasicMutex::tryLock;
136 bool tryLock(int timeout) noexcept(FutexAlwaysAvailable)
137 {
138 return tryLock(QDeadlineTimer(timeout));
139 }
140
141 bool tryLock(QDeadlineTimer timeout) noexcept(FutexAlwaysAvailable)
142 {
143 unsigned tsanFlags = QtTsan::TryLock;
144 QtTsan::mutexPreLock(this, tsanFlags);
145
146 bool success = fastTryLock();
147
148 if (success) {
149 QtTsan::mutexPostLock(this, tsanFlags, 0);
150 return success;
151 }
152
153 success = lockInternal(timeout);
154
155 if (!success)
156 tsanFlags |= QtTsan::TryLockFailed;
157 QtTsan::mutexPostLock(this, tsanFlags, 0);
158
159 return success;
160 }
161
162 // TimedLockable concept
163 template <class Rep, class Period>
164 bool try_lock_for(std::chrono::duration<Rep, Period> duration)
165 {
166 return tryLock(QDeadlineTimer(duration));
167 }
168
169 // TimedLockable concept
170 template<class Clock, class Duration>
171 bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
172 {
173 return tryLock(QDeadlineTimer(timePoint));
174 }
175};
176
177class Q_CORE_EXPORT QRecursiveMutex
178{
179 Q_DISABLE_COPY_MOVE(QRecursiveMutex)
180 // written to by the thread that first owns 'mutex';
181 // read during attempts to acquire ownership of 'mutex' from any other thread:
182 QAtomicPointer<void> owner = nullptr;
183 // only ever accessed from the thread that owns 'mutex':
184 uint count = 0;
185 QMutex mutex;
186 static constexpr bool LockIsNoexcept = noexcept(std::declval<QMutex>().lock());
187
188public:
189 constexpr QRecursiveMutex() = default;
190 ~QRecursiveMutex();
191
192
193 // BasicLockable concept
194 void lock() noexcept(LockIsNoexcept)
195 { tryLock(QDeadlineTimer(QDeadlineTimer::Forever)); }
196 QT_CORE_INLINE_SINCE(6, 6)
197 bool tryLock(int timeout) noexcept(LockIsNoexcept);
198 bool tryLock(QDeadlineTimer timer = {}) noexcept(LockIsNoexcept);
199 // BasicLockable concept
200 void unlock() noexcept;
201
202 // Lockable concept
203 bool try_lock() noexcept(LockIsNoexcept) { return tryLock(); }
204
205 // TimedLockable concept
206 template <class Rep, class Period>
207 bool try_lock_for(std::chrono::duration<Rep, Period> duration)
208 {
209 return tryLock(QDeadlineTimer(duration));
210 }
211
212 // TimedLockable concept
213 template<class Clock, class Duration>
214 bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
215 {
216 return tryLock(QDeadlineTimer(timePoint));
217 }
218};
219
220#if QT_CORE_INLINE_IMPL_SINCE(6, 6)
221bool QRecursiveMutex::tryLock(int timeout) noexcept(LockIsNoexcept)
222{
223 return tryLock(QDeadlineTimer(timeout));
224}
225#endif
226
227template <typename Mutex>
228class QMutexLocker
229{
230#ifdef Q_CC_GHS
231 // internal compiler error otherwise
232 static constexpr bool LockIsNoexcept = false;
233#else
234 static constexpr bool LockIsNoexcept = noexcept(std::declval<Mutex>().lock());
235#endif
236public:
237 Q_NODISCARD_CTOR
238 inline explicit QMutexLocker(Mutex *mutex) noexcept(LockIsNoexcept)
239 {
240 m_mutex = mutex;
241 if (Q_LIKELY(mutex)) {
242 mutex->lock();
243 m_isLocked = true;
244 }
245 }
246
247 Q_NODISCARD_CTOR
248 inline QMutexLocker(QMutexLocker &&other) noexcept
249 : m_mutex(std::exchange(other.m_mutex, nullptr)),
250 m_isLocked(std::exchange(other.m_isLocked, false))
251 {}
252
253 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMutexLocker)
254
255 inline ~QMutexLocker()
256 {
257 if (m_isLocked)
258 unlock();
259 }
260
261 inline bool isLocked() const noexcept
262 {
263 return m_isLocked;
264 }
265
266 inline void unlock() noexcept
267 {
268 Q_ASSERT(m_isLocked);
269 m_mutex->unlock();
270 m_isLocked = false;
271 }
272
273 inline void relock() noexcept(LockIsNoexcept)
274 {
275 Q_ASSERT(!m_isLocked);
276 m_mutex->lock();
277 m_isLocked = true;
278 }
279
280 inline void swap(QMutexLocker &other) noexcept
281 {
282 qt_ptr_swap(m_mutex, other.m_mutex);
283 std::swap(m_isLocked, other.m_isLocked);
284 }
285
286 Mutex *mutex() const
287 {
288 return m_mutex;
289 }
290private:
291 Q_DISABLE_COPY(QMutexLocker)
292
293 Mutex *m_mutex;
294 bool m_isLocked = false;
295};
296
297#else // !QT_CONFIG(thread) && !Q_QDOC
298
299class QMutex
300{
301public:
302
303 constexpr QMutex() noexcept { }
304
305 inline void lock() noexcept {}
306 inline bool tryLock(int timeout = 0) noexcept { Q_UNUSED(timeout); return true; }
307 inline bool try_lock() noexcept { return true; }
308 inline void unlock() noexcept {}
309
310 template <class Rep, class Period>
311 inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) noexcept
312 {
313 Q_UNUSED(duration);
314 return true;
315 }
316
317 template<class Clock, class Duration>
318 inline bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) noexcept
319 {
320 Q_UNUSED(timePoint);
321 return true;
322 }
323
324private:
325 Q_DISABLE_COPY(QMutex)
326};
327
328class QRecursiveMutex : public QMutex {};
329
330template <typename Mutex>
332{
333public:
335 inline explicit QMutexLocker(Mutex *) noexcept {}
336 inline ~QMutexLocker() noexcept {}
337
338 inline void unlock() noexcept {}
339 void relock() noexcept {}
340 inline Mutex *mutex() const noexcept { return nullptr; }
341
342private:
344};
345
346typedef QMutex QBasicMutex;
347
348#endif // !QT_CONFIG(thread) && !Q_QDOC
349
350QT_END_NAMESPACE
351
352#endif // QMUTEX_H
QByteArray & operator*() noexcept
Definition qbytearray.h:803
QByteArray::Base64DecodingStatus decodingStatus
Definition qbytearray.h:788
friend bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
Returns true if lhs and rhs are equal, otherwise returns false.
Definition qbytearray.h:807
void swap(QByteArray::FromBase64Result &other) noexcept
Definition qbytearray.h:790
operator bool() const noexcept
\variable QByteArray::FromBase64Result::decoded
Definition qbytearray.h:796
const QByteArray & operator*() const noexcept
Returns the decoded byte array.
Definition qbytearray.h:804
friend bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
Returns true if lhs and rhs are different, otherwise returns false.
Definition qbytearray.h:818
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatastream.h:49
\inmodule QtCore
Definition qeventloop.h:59
int initFrom(const QMessageLogContext &logContext)
void populateBacktrace(int frameCount)
QInternalMessageLogContext(const QMessageLogContext &logContext, const QLoggingCategory &categoryOverride)
Definition qlogging_p.h:65
std::optional< BacktraceStorage > backtrace
Definition qlogging_p.h:57
static constexpr int DefaultBacktraceDepth
Definition qlogging_p.h:47
Definition qlist.h:80
\inmodule QtCore
Definition qlogging.h:43
constexpr QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName) noexcept
Definition qlogging.h:48
const char * category
Definition qlogging.h:55
constexpr QMessageLogContext() noexcept=default
const char * function
Definition qlogging.h:54
const char * file
Definition qlogging.h:53
\inmodule QtCore
Definition qlogging.h:73
QDebug debug(CategoryFunction catFunc) const
QDebug debug(const QLoggingCategory &cat) const
Logs a debug message into category cat using a QDebug stream.
Definition qlogging.cpp:450
void void void void Q_DECL_COLD_FUNCTION void Q_DECL_COLD_FUNCTION void Q_DECL_COLD_FUNCTION void Q_DECL_COLD_FUNCTION void QT_MESSAGE_LOGGER_NORETURN Q_DECL_COLD_FUNCTION void QT_MESSAGE_LOGGER_NORETURN Q_DECL_COLD_FUNCTION void QDebug debug() const
Logs a debug message using a QDebug stream.
Definition qlogging.cpp:436
QDebug info(const QLoggingCategory &cat) const
Logs an informational message into the category cat using a QDebug stream.
Definition qlogging.cpp:539
QDebug info() const
Logs an informational message using a QDebug stream.
Definition qlogging.cpp:525
QNoDebug noDebug(...) const noexcept
QDebug info(CategoryFunction catFunc) const
\inmodule QtCore
Definition qmutex.h:332
Mutex * mutex() const noexcept
Returns the mutex on which the QMutexLocker is operating.
Definition qmutex.h:340
void unlock() noexcept
Unlocks this mutex locker.
Definition qmutex.h:338
~QMutexLocker() noexcept
Destroys the QMutexLocker and unlocks the mutex that was locked in the constructor.
Definition qmutex.h:336
void relock() noexcept
Relocks an unlocked mutex locker.
Definition qmutex.h:339
\inmodule QtCore
Definition qmutex.h:328
static Q_CONSTINIT thread_local bool msgHandlerGrabbed
static const char ifCriticalTokenC[]
static const char emptyTokenC[]
static Q_NEVER_INLINE void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg, va_list ap)
Definition qlogging.cpp:333
static void preformattedMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &formattedMessage)
static bool systemHasStderr()
Returns true if writing to stderr is supported.
Definition qlogging.cpp:187
static const char endifTokenC[]
static bool isDefaultCategory(const char *category)
Definition qlogging.cpp:879
static const char messageTokenC[]
static constexpr SystemMessageSink systemMessageSink
static void qt_maybe_message_fatal(QtMsgType, const QMessageLogContext &context, String &&message)
\inmodule QtCore \title Qt Logging Types
#define HANDLE_IF_TOKEN(LEVEL)
Q_DECLARE_TYPEINFO(QMessagePattern::BacktraceParams, Q_RELOCATABLE_TYPE)
static const char timeTokenC[]
static bool is_fatal_count_down(QAtomicInt &n)
Definition qlogging.cpp:150
static const char qthreadptrTokenC[]
static const char fileTokenC[]
static const char ifDebugTokenC[]
static const char ifFatalTokenC[]
static const char categoryTokenC[]
static const char lineTokenC[]
static const char typeTokenC[]
static const char ifCategoryTokenC[]
static int checked_var_value(const char *varname)
Definition qlogging.cpp:136
static const char pidTokenC[]
Q_TRACE_POINT(qtcore, qt_message_print, int type, const char *category, const char *function, const char *file, int line, const QString &message)
static const char threadidTokenC[]
static QString formatLogMessage(QtMsgType type, const QMessageLogContext &context, const QString &str)
static const char backtraceTokenC[]
static const char functionTokenC[]
#define IF_TOKEN(LEVEL)
static const char ifWarningTokenC[]
static const char appnameTokenC[]
static bool isFatal(QtMsgType msgType)
Definition qlogging.cpp:161
static const char ifInfoTokenC[]
static void qt_message_print(QtMsgType, const QMessageLogContext &context, const QString &message)
static bool stderrHasConsoleAttached()
Returns true if writing to stderr will end up in a console/terminal visible to the user.
Definition qlogging.cpp:212
Combined button and popup list for selecting options.
QDebug printAssociativeContainer(QDebug debug, const char *which, const AssociativeContainer &c)
Definition qdebug.h:386
bool shouldLogToStderr()
Returns true if logging stderr should be ensured.
Definition qlogging.cpp:265
QDebug printSequentialContainer(QDebug debug, const char *which, const SequentialContainer &c)
Definition qdebug.h:368
QByteArray operator""_ba(const char *str, size_t size) noexcept
Definition qbytearray.h:853
Definition qcompare.h:76
QT_BEGIN_NAMESPACE Q_NORETURN void qAbort()
Definition qassert.cpp:24
QByteArray operator+(const QByteArray &a1, const char *a2)
Definition qbytearray.h:709
QByteArray qUncompress(const QByteArray &data)
Definition qbytearray.h:778
QByteArray operator+(char a1, const QByteArray &a2)
Definition qbytearray.h:719
QByteArray operator+(QByteArray &&lhs, char rhs)
Definition qbytearray.h:715
QByteArray operator+(const QByteArray &a1, char a2)
Definition qbytearray.h:713
QByteArray operator+(const char *a1, const QByteArray &a2)
Definition qbytearray.h:717
QByteArray operator+(QByteArray &&lhs, const QByteArray &rhs)
Definition qbytearray.h:707
qsizetype erase_if(QByteArray &ba, Predicate pred)
Definition qbytearray.h:836
QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
Definition qbytearray.h:705
QByteArray qCompress(const QByteArray &data, int compressionLevel=-1)
Definition qbytearray.h:776
#define QT5_NULL_STRINGS
Definition qbytearray.h:25
qsizetype erase(QByteArray &ba, const T &t)
Definition qbytearray.h:830
QByteArray operator+(QByteArray &&lhs, const char *rhs)
Definition qbytearray.h:711
#define __has_builtin(x)
#define __has_include(x)
#define __has_cpp_attribute(x)
void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
Definition qdebug.h:615
Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, quint64 value)
Definition qdebug.cpp:1415
Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value)
Definition qdebug.cpp:1406
Q_CORE_EXPORT QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2462
#define QT_MESSAGELOG_FUNC
Definition qlogging.h:161
Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void qErrnoWarning(int code, const char *msg,...)
Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void qErrnoWarning(const char *msg,...)
#define QT_MESSAGELOG_FILE
Definition qlogging.h:159
#define QT_MESSAGE_LOGGER_NORETURN
Definition qlogging.h:69
#define QT_MESSAGELOG_LINE
Definition qlogging.h:160
Q_CORE_EXPORT void qSetMessagePattern(const QString &messagePattern)
#define QT_MESSAGELOGCONTEXT
Definition qlogging.h:154
QtMsgType
Definition qlogging.h:29
@ QtCriticalMsg
Definition qlogging.h:33
@ QtFatalMsg
Definition qlogging.h:34
@ QtDebugMsg
Definition qlogging.h:30
Q_CORE_EXPORT void qt_message_output(QtMsgType, const QMessageLogContext &context, const QString &message)
void(* QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &)
Definition qlogging.h:196
#define Q_LOGGING_CATEGORY(name,...)
#define QT_MESSAGE_LOGGER_COMMON(category, level)
#define Q_DECLARE_LOGGING_CATEGORY(name)
QMutex QBasicMutex
Definition qmutex.h:346
void setPattern(const QString &pattern)
std::unique_ptr< std::unique_ptr< const char[]>[]> literals
std::chrono::steady_clock::time_point appStartTime
std::unique_ptr< const char *[]> tokens
QList< QString > timeArgs
static QBasicMutex mutex
void setDefaultPattern()
static constexpr bool Value
Definition qdebug.h:680
static constexpr bool Value
Definition qdebug.h:676