From 7a374c38d288435b3c0a76b82a1c2ca53ea9c003 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Wed, 25 Jan 2023 12:53:32 +0100 Subject: [PATCH] QThread: Introduce isCurrentThread This allows a more efficient way of checking whether a thread is the currently executing one (without using private API). Change-Id: I007edae6b258d7e42e901fa720d4f3cf9fe25a49 Reviewed-by: Fabian Kosmale Reviewed-by: Jarek Kobus Reviewed-by: David Faure --- src/corelib/thread/qthread.cpp | 35 +++++++++++++++++++ src/corelib/thread/qthread.h | 2 ++ src/corelib/thread/qthread_p.h | 1 + .../corelib/thread/qthread/tst_qthread.cpp | 7 ++++ 4 files changed, 45 insertions(+) diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index a9115c5b397..2cac443e53f 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -913,6 +913,36 @@ int QThread::loopLevel() const return d->data->eventLoops.size(); } +/*! + \internal + Returns the thread handle of this thread. + It can be compared with the return value of currentThreadId(). + + This is used to implement isCurrentThread, and might be useful + for debugging (e.g. by comparing the value in gdb with info threads). + + \note Thread handles of destroyed threads might be reused by the + operating system. Storing the return value of this function can + therefore give surprising results if it outlives the QThread object + (threads claimed to be the same even if they aren't). +*/ +Qt::HANDLE QThreadPrivate::threadId() const +{ + return data->threadId.loadRelaxed(); +} + +/*! + \since 6.8 + Returns true if this thread is QThread::currentThread. + + \sa currentThreadId() +*/ +bool QThread::isCurrentThread() const +{ + Q_D(const QThread); + return QThread::currentThreadId() == d->threadId(); +} + #else // QT_CONFIG(thread) QThread::QThread(QObject *parent) @@ -985,6 +1015,11 @@ QThread *QThread::currentThread() return QThreadData::current()->thread.loadAcquire(); } +bool QThread::isCurrentThread() const +{ + return true; +} + int QThread::idealThreadCount() noexcept { return 1; diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index a4b7183b5a7..fcef6deb598 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -68,6 +68,8 @@ public: bool event(QEvent *event) override; int loopLevel() const; + bool isCurrentThread() const; + template [[nodiscard]] static QThread *create(Function &&f, Args &&... args); diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 2335ba398d0..c39e21ec9a2 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -179,6 +179,7 @@ public: ~QThreadPrivate(); void setPriority(QThread::Priority prio); + Qt::HANDLE threadId() const; mutable QMutex mutex; QAtomicInt quitLockRef; diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp index 9a53c5a48d1..b163235d818 100644 --- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp +++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp @@ -137,11 +137,13 @@ class Current_Thread : public QThread public: Qt::HANDLE id; QThread *thread; + bool runCalledInCurrentThread = false; void run() override { id = QThread::currentThreadId(); thread = QThread::currentThread(); + runCalledInCurrentThread = thread->isCurrentThread(); } }; @@ -276,6 +278,11 @@ void tst_QThread::currentThreadId() QVERIFY(thread.wait(five_minutes)); QVERIFY(thread.id != nullptr); QVERIFY(thread.id != QThread::currentThreadId()); + QVERIFY(!thread.isCurrentThread()); + QVERIFY(!thread.thread->isCurrentThread()); + QVERIFY(thread.QThread::thread()->isCurrentThread()); + QVERIFY(thread.runCalledInCurrentThread); + QVERIFY(qApp->thread()->isCurrentThread()); } void tst_QThread::currentThread()