QThread: Introduce static isMainThread() helper

Useful for QtCreator, as a replacement for
Utils::isMainThread() inside threadutils.h,
may serve for other projects, too.

Introduce static QCoreApplicationPrivate::theMainThreadId
atomic helper field holding the id of the main thread.

Change-Id: Iccc0302f423f47b5ecad86c4cd3de4d1ee36155f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Jarek Kobus 2024-03-18 21:19:02 +01:00
parent 7a374c38d2
commit a3d50112e4
6 changed files with 30 additions and 4 deletions

View File

@ -525,6 +525,7 @@ void QCoreApplicationPrivate::eventDispatcherReady()
}
Q_CONSTINIT QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
Q_CONSTINIT QBasicAtomicPointer<void> QCoreApplicationPrivate::theMainThreadId = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
QThread *QCoreApplicationPrivate::mainThread()
{
Q_ASSERT(theMainThread.loadRelaxed() != nullptr);

View File

@ -108,6 +108,7 @@ public:
virtual void quit();
static QBasicAtomicPointer<QThread> theMainThread;
static QBasicAtomicPointer<void> theMainThreadId;
static QThread *mainThread();
static bool threadRequiresCoreApplication();

View File

@ -66,8 +66,9 @@ QThreadData::~QThreadData()
// safeguard the main thread here.. This fix is a bit crude, but it solves
// the problem...
if (this->thread.loadAcquire() == QCoreApplicationPrivate::theMainThread.loadAcquire()) {
QCoreApplicationPrivate::theMainThread.storeRelease(nullptr);
QThreadData::clearCurrentThreadData();
QCoreApplicationPrivate::theMainThread.storeRelease(nullptr);
QCoreApplicationPrivate::theMainThreadId.storeRelaxed(nullptr);
QThreadData::clearCurrentThreadData();
}
// ~QThread() sets thread to nullptr, so if it isn't null here, it's
@ -425,6 +426,23 @@ QThread *QThread::currentThread()
return data->thread.loadAcquire();
}
/*!
\since 6.8
Returns whether the currently executing thread is the main thread.
The main thread is the thread in which QCoreApplication was created.
This is usually the thread that called the \c{main()} function, but not necessarily so.
It is the thread that is processing the GUI events and in which graphical objects
(QWindow, QWidget) can be created.
\sa currentThread(), QCoreApplication::instance()
*/
bool QThread::isMainThread()
{
return currentThreadId() == QCoreApplicationPrivate::theMainThreadId.loadRelaxed();
}
/*!
Constructs a new QThread to manage a new thread. The \a parent
takes ownership of the QThread. The thread does not begin
@ -1066,8 +1084,10 @@ QThreadData *QThreadData::current(bool createIfNecessary)
data->threadId.storeRelaxed(Qt::HANDLE(data->thread.loadAcquire()));
data->deref();
data->isAdopted = true;
if (!QCoreApplicationPrivate::theMainThread.loadAcquire())
if (!QCoreApplicationPrivate::theMainThread.loadAcquire()) {
QCoreApplicationPrivate::theMainThread.storeRelease(data->thread.loadRelaxed());
QCoreApplicationPrivate::theMainThreadId.storeRelaxed(data->threadId.loadRelaxed());
}
}
return data;
}

View File

@ -30,6 +30,7 @@ class Q_CORE_EXPORT QThread : public QObject
public:
static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
static QThread *currentThread();
static bool isMainThread();
static int idealThreadCount() noexcept;
static void yieldCurrentThread();

View File

@ -191,8 +191,10 @@ QThreadData *QThreadData::current(bool createIfNecessary)
data->deref();
data->isAdopted = true;
data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
if (!QCoreApplicationPrivate::theMainThread.loadAcquire())
if (!QCoreApplicationPrivate::theMainThread.loadAcquire()) {
QCoreApplicationPrivate::theMainThread.storeRelease(data->thread.loadRelaxed());
QCoreApplicationPrivate::theMainThreadId.storeRelaxed(data->threadId.loadRelaxed());
}
}
return data;
}

View File

@ -89,6 +89,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
if (!QCoreApplicationPrivate::theMainThread) {
QCoreApplicationPrivate::theMainThread = threadData->thread.loadRelaxed();
QCoreApplicationPrivate::theMainThreadId.storeRelaxed(threadData->threadId.loadRelaxed());
} else {
HANDLE realHandle = INVALID_HANDLE_VALUE;
DuplicateHandle(GetCurrentProcess(),