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// Qt-Security score:significant reason:default
4
5#ifndef QMUTEX_H
6#define QMUTEX_H
7
8#include <QtCore/qglobal.h>
9#include <QtCore/qatomic.h>
10#include <QtCore/qdeadlinetimer.h>
11#include <QtCore/qtsan_impl.h>
12
13#include <chrono>
14
16
17#if QT_CONFIG(thread) || defined(Q_QDOC)
18
19class QMutex;
20class QRecursiveMutex;
21class QMutexPrivate;
22
23class QT6_ONLY(Q_CORE_EXPORT) QBasicMutex
24{
25 Q_DISABLE_COPY_MOVE(QBasicMutex)
26protected:
27 static constexpr bool FutexAlwaysAvailable =
28#if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) || defined(Q_OS_WIN) // these platforms use futex
29 true
30#else
31 false
32#endif
33 ;
34
35public:
36 constexpr QBasicMutex()
37 : d_ptr(nullptr)
38 {}
39
40 // BasicLockable concept
41 inline void lock() noexcept(FutexAlwaysAvailable) {
42 QtTsan::mutexPreLock(this, 0u);
43
44 if (!fastTryLock())
45 lockInternal();
46
47 QtTsan::mutexPostLock(this, 0u, 0);
48 }
49
50 // BasicLockable concept
51 inline void unlock() noexcept {
52 Q_ASSERT(d_ptr.loadRelaxed()); //mutex must be locked
53
54 QtTsan::mutexPreUnlock(this, 0u);
55
56 if constexpr (FutexAlwaysAvailable) {
57 // we always unlock if we have futexes
58 if (QMutexPrivate *d = d_ptr.fetchAndStoreRelease(nullptr); Q_UNLIKELY(d != dummyLocked()))
59 unlockInternalFutex(d); // was contended
60 } else {
61 // if we don't have futexes, we can only unlock if not contended
62 if (QMutexPrivate *d; !d_ptr.testAndSetRelease(dummyLocked(), nullptr, d))
63 unlockInternal(d); // was contended
64 }
65
66 QtTsan::mutexPostUnlock(this, 0u);
67 }
68
69 bool tryLock() noexcept {
70 unsigned tsanFlags = QtTsan::TryLock;
71 QtTsan::mutexPreLock(this, tsanFlags);
72
73 const bool success = fastTryLock();
74
75 if (!success)
76 tsanFlags |= QtTsan::TryLockFailed;
77 QtTsan::mutexPostLock(this, tsanFlags, 0);
78
79 return success;
80 }
81
82 // Lockable concept
83 bool try_lock() noexcept { return tryLock(); }
84
85private:
86 inline bool fastTryLock() noexcept
87 {
88 if (Q_UNLIKELY(d_ptr.loadRelaxed() != nullptr))
89 return false;
90 return d_ptr.testAndSetAcquire(nullptr, dummyLocked());
91 }
92#if QT_CORE_REMOVED_SINCE(6, 10)
93 inline bool fastTryUnlock() noexcept {
94 return d_ptr.testAndSetRelease(dummyLocked(), nullptr);
95 }
96#endif
97
98 QT7_ONLY(Q_CORE_EXPORT)
99 void lockInternal() noexcept(FutexAlwaysAvailable);
100 QT7_ONLY(Q_CORE_EXPORT)
101 bool lockInternal(QDeadlineTimer timeout) noexcept(FutexAlwaysAvailable);
102#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
103 bool lockInternal(int timeout) noexcept(FutexAlwaysAvailable);
104 void unlockInternal() noexcept;
105#endif
106 QT7_ONLY(Q_CORE_EXPORT)
107 void unlockInternalFutex(void *d) noexcept;
108 QT7_ONLY(Q_CORE_EXPORT)
109 void unlockInternal(void *d) noexcept;
110#if QT_CORE_REMOVED_SINCE(6, 9)
111 void destroyInternal(QMutexPrivate *d);
112#endif
113 QT7_ONLY(Q_CORE_EXPORT)
114 void destroyInternal(void *d);
115
116 QBasicAtomicPointer<QMutexPrivate> d_ptr;
117 static inline QMutexPrivate *dummyLocked() {
118 return reinterpret_cast<QMutexPrivate *>(quintptr(1));
119 }
120
121 friend class QMutex;
122 friend class QMutexPrivate;
123};
124
125class QT6_ONLY(Q_CORE_EXPORT) QMutex : public QBasicMutex
126{
127public:
128 constexpr QMutex() = default;
129 ~QMutex()
130 {
131 QMutexPrivate *d = d_ptr.loadRelaxed();
132 if (d)
133 destroyInternal(d);
134 }
135
136#ifdef Q_QDOC
137 inline void lock() noexcept(FutexAlwaysAvailable);
138 inline void unlock() noexcept;
139 bool tryLock() noexcept;
140#endif
141
142 // Lockable concept
143 bool try_lock() noexcept { return tryLock(); }
144
145
146 using QBasicMutex::tryLock;
147 bool tryLock(int timeout) noexcept(FutexAlwaysAvailable)
148 {
149 return tryLock(QDeadlineTimer(timeout));
150 }
151
152 bool tryLock(QDeadlineTimer timeout) noexcept(FutexAlwaysAvailable)
153 {
154 unsigned tsanFlags = QtTsan::TryLock;
155 QtTsan::mutexPreLock(this, tsanFlags);
156
157 bool success = fastTryLock();
158
159 if (success) {
160 QtTsan::mutexPostLock(this, tsanFlags, 0);
161 return success;
162 }
163
164 success = lockInternal(timeout);
165
166 if (!success)
167 tsanFlags |= QtTsan::TryLockFailed;
168 QtTsan::mutexPostLock(this, tsanFlags, 0);
169
170 return success;
171 }
172
173 // TimedLockable concept
174 template <class Rep, class Period>
175 bool try_lock_for(std::chrono::duration<Rep, Period> duration)
176 {
177 return tryLock(QDeadlineTimer(duration));
178 }
179
180 // TimedLockable concept
181 template<class Clock, class Duration>
182 bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
183 {
184 return tryLock(QDeadlineTimer(timePoint));
185 }
186};
187
188class QT6_ONLY(Q_CORE_EXPORT) QRecursiveMutex
189{
190 Q_DISABLE_COPY_MOVE(QRecursiveMutex)
191 // written to by the thread that first owns 'mutex';
192 // read during attempts to acquire ownership of 'mutex' from any other thread:
193 QAtomicPointer<void> owner = nullptr;
194 // only ever accessed from the thread that owns 'mutex':
195 uint count = 0;
196 QMutex mutex;
197 static constexpr bool LockIsNoexcept = noexcept(std::declval<QMutex>().lock());
198
199public:
200 constexpr QRecursiveMutex() = default;
201 QT7_ONLY(Q_CORE_EXPORT)
202 ~QRecursiveMutex();
203
204
205 // BasicLockable concept
206 void lock() noexcept(LockIsNoexcept)
207 { tryLock(QDeadlineTimer(QDeadlineTimer::Forever)); }
208 QT_CORE_INLINE_SINCE(6, 6)
209 bool tryLock(int timeout) noexcept(LockIsNoexcept);
210 QT7_ONLY(Q_CORE_EXPORT)
211 bool tryLock(QDeadlineTimer timer = {}) noexcept(LockIsNoexcept);
212 // BasicLockable concept
213 QT7_ONLY(Q_CORE_EXPORT)
214 void unlock() noexcept;
215
216 // Lockable concept
217 bool try_lock() noexcept(LockIsNoexcept) { return tryLock(); }
218
219 // TimedLockable concept
220 template <class Rep, class Period>
221 bool try_lock_for(std::chrono::duration<Rep, Period> duration)
222 {
223 return tryLock(QDeadlineTimer(duration));
224 }
225
226 // TimedLockable concept
227 template<class Clock, class Duration>
228 bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
229 {
230 return tryLock(QDeadlineTimer(timePoint));
231 }
232};
233
234#if QT_CORE_INLINE_IMPL_SINCE(6, 6)
235bool QRecursiveMutex::tryLock(int timeout) noexcept(LockIsNoexcept)
236{
237 return tryLock(QDeadlineTimer(timeout));
238}
239#endif
240
241template <typename Mutex>
242class QMutexLocker
243{
244#ifdef Q_CC_GHS
245 // internal compiler error otherwise
246 static constexpr bool LockIsNoexcept = false;
247#else
248 static constexpr bool LockIsNoexcept = noexcept(std::declval<Mutex>().lock());
249#endif
250public:
251 Q_NODISCARD_CTOR
252 inline explicit QMutexLocker(Mutex *mutex) noexcept(LockIsNoexcept)
253 {
254 m_mutex = mutex;
255 if (Q_LIKELY(mutex)) {
256 mutex->lock();
257 m_isLocked = true;
258 }
259 }
260
261 Q_NODISCARD_CTOR
262 inline QMutexLocker(QMutexLocker &&other) noexcept
263 : m_mutex(std::exchange(other.m_mutex, nullptr)),
264 m_isLocked(std::exchange(other.m_isLocked, false))
265 {}
266
267 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMutexLocker)
268
269 inline ~QMutexLocker()
270 {
271 if (m_isLocked)
272 unlock();
273 }
274
275 inline bool isLocked() const noexcept
276 {
277 return m_isLocked;
278 }
279
280 inline void unlock() noexcept
281 {
282 Q_ASSERT(m_isLocked);
283 m_mutex->unlock();
284 m_isLocked = false;
285 }
286
287 inline void relock() noexcept(LockIsNoexcept)
288 {
289 Q_ASSERT(!m_isLocked);
290 m_mutex->lock();
291 m_isLocked = true;
292 }
293
294 inline void swap(QMutexLocker &other) noexcept
295 {
296 qt_ptr_swap(m_mutex, other.m_mutex);
297 std::swap(m_isLocked, other.m_isLocked);
298 }
299
300 Mutex *mutex() const
301 {
302 return m_mutex;
303 }
304private:
305 Q_DISABLE_COPY(QMutexLocker)
306
307 Mutex *m_mutex;
308 bool m_isLocked = false;
309};
310
311#else // !QT_CONFIG(thread) && !Q_QDOC
312
313class QMutex
314{
315public:
316
317 constexpr QMutex() noexcept { }
318
319 inline void lock() noexcept {}
320 inline bool tryLock(int timeout = 0) noexcept { Q_UNUSED(timeout); return true; }
321 inline bool try_lock() noexcept { return true; }
322 inline void unlock() noexcept {}
323
324 template <class Rep, class Period>
325 inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) noexcept
326 {
327 Q_UNUSED(duration);
328 return true;
329 }
330
331 template<class Clock, class Duration>
332 inline bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) noexcept
333 {
334 Q_UNUSED(timePoint);
335 return true;
336 }
337
338private:
339 Q_DISABLE_COPY(QMutex)
340};
341
342class QRecursiveMutex : public QMutex {};
343
344template <typename Mutex>
346{
347public:
349 inline explicit QMutexLocker(Mutex *) noexcept {}
350 inline ~QMutexLocker() noexcept {}
351
352 inline void unlock() noexcept {}
353 void relock() noexcept {}
354 inline Mutex *mutex() const noexcept { return nullptr; }
355
356private:
358};
359
360typedef QMutex QBasicMutex;
361
362#endif // !QT_CONFIG(thread) && !Q_QDOC
363
364QT_END_NAMESPACE
365
366#endif // QMUTEX_H
QByteArray & operator*() noexcept
Definition qbytearray.h:797
QByteArray::Base64DecodingStatus decodingStatus
Definition qbytearray.h:782
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:801
void swap(QByteArray::FromBase64Result &other) noexcept
Definition qbytearray.h:784
operator bool() const noexcept
\variable QByteArray::FromBase64Result::decoded
Definition qbytearray.h:790
const QByteArray & operator*() const noexcept
Returns the decoded byte array.
Definition qbytearray.h:798
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:812
\inmodule QtCore
Definition qbytearray.h:58
\inmodule QtCore\reentrant
Definition qdatastream.h:50
\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:525
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:511
QDebug info(const QLoggingCategory &cat) const
Logs an informational message into the category cat using a QDebug stream.
Definition qlogging.cpp:614
QDebug info() const
Logs an informational message using a QDebug stream.
Definition qlogging.cpp:600
QNoDebug noDebug(...) const noexcept
QDebug info(CategoryFunction catFunc) const
\inmodule QtCore
Definition qmutex.h:346
Mutex * mutex() const noexcept
Returns the mutex on which the QMutexLocker is operating.
Definition qmutex.h:354
void unlock() noexcept
Unlocks this mutex locker.
Definition qmutex.h:352
~QMutexLocker() noexcept
Destroys the QMutexLocker and unlocks the mutex that was locked in the constructor.
Definition qmutex.h:350
void relock() noexcept
Relocks an unlocked mutex locker.
Definition qmutex.h:353
\inmodule QtCore
Definition qmutex.h:342
static Q_CONSTINIT thread_local bool msgHandlerGrabbed
static const char ifCriticalTokenC[]
static bool grabMessageHandler()
void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const QString &message)
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:408
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:262
static const char endifTokenC[]
static bool isDefaultCategory(const char *category)
Definition qlogging.cpp:954
static const char messageTokenC[]
static bool qt_append_thread_name_to(QString &message)
Definition qlogging.cpp:247
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 void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &buf)
static const char timeTokenC[]
static bool isFatalCountDown(const char *varname, QBasicAtomicInt &n)
Definition qlogging.cpp:152
void qErrnoWarning(int code, const char *msg,...)
static const char qthreadptrTokenC[]
static const char fileTokenC[]
static const char ifDebugTokenC[]
static const char ifFatalTokenC[]
static const char categoryTokenC[]
static void stderr_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &formattedMessage)
static const char lineTokenC[]
static const char typeTokenC[]
static void ungrabMessageHandler()
static void copyInternalContext(QInternalMessageLogContext *self, const QMessageLogContext &logContext) noexcept
static const char ifCategoryTokenC[]
static int checked_var_value(const char *varname)
Definition qlogging.cpp:138
static const char threadnameTokenC[]
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[]
void qErrnoWarning(const char *msg,...)
static const char functionTokenC[]
#define IF_TOKEN(LEVEL)
static const char ifWarningTokenC[]
static const char appnameTokenC[]
static bool isFatal(QtMsgType msgType)
Definition qlogging.cpp:186
static const char ifInfoTokenC[]
QtMessageHandler qInstallMessageHandler(QtMessageHandler h)
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:287
void qSetMessagePattern(const QString &pattern)
QDebug printAssociativeContainer(QDebug debug, const char *which, const AssociativeContainer &c)
Definition qdebug.h:385
bool shouldLogToStderr()
Returns true if logging stderr should be ensured.
Definition qlogging.cpp:340
QDebug printSequentialContainer(QDebug debug, const char *which, const SequentialContainer &c)
Definition qdebug.h:367
QByteArray operator""_ba(const char *str, size_t size) noexcept
Definition qbytearray.h:847
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:703
QByteArray qUncompress(const QByteArray &data)
Definition qbytearray.h:772
QByteArray operator+(char a1, const QByteArray &a2)
Definition qbytearray.h:713
QByteArray operator+(QByteArray &&lhs, char rhs)
Definition qbytearray.h:709
QByteArray operator+(const QByteArray &a1, char a2)
Definition qbytearray.h:707
QByteArray operator+(const char *a1, const QByteArray &a2)
Definition qbytearray.h:711
QByteArray operator+(QByteArray &&lhs, const QByteArray &rhs)
Definition qbytearray.h:701
qsizetype erase_if(QByteArray &ba, Predicate pred)
Definition qbytearray.h:830
QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
Definition qbytearray.h:699
QByteArray qCompress(const QByteArray &data, int compressionLevel=-1)
Definition qbytearray.h:770
#define QT5_NULL_STRINGS
Definition qbytearray.h:26
qsizetype erase(QByteArray &ba, const T &t)
Definition qbytearray.h:824
QByteArray operator+(QByteArray &&lhs, const char *rhs)
Definition qbytearray.h:705
#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:614
Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, quint64 value)
Definition qdebug.cpp:1428
Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value)
Definition qdebug.cpp:1419
Q_CORE_EXPORT QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2568
#define QT_MESSAGELOG_FUNC
Definition qlogging.h:161
#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:360
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:679
static constexpr bool Value
Definition qdebug.h:675