summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qthread_win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/thread/qthread_win.cpp')
-rw-r--r--src/corelib/thread/qthread_win.cpp139
1 files changed, 52 insertions, 87 deletions
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 820ffa1149..ee3b94dc3b 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qthread.h"
#include "qthread_p.h"
@@ -55,6 +19,17 @@
#endif // _MT
#include <process.h>
+extern "C" {
+// MinGW is missing the declaration of SetThreadDescription:
+WINBASEAPI
+HRESULT
+WINAPI
+SetThreadDescription(
+ _In_ HANDLE hThread,
+ _In_ PCWSTR lpThreadDescription
+ );
+}
+
QT_BEGIN_NAMESPACE
#if QT_CONFIG(thread)
@@ -67,7 +42,7 @@ void qt_create_tls()
{
if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES)
return;
- static QBasicMutex mutex;
+ Q_CONSTINIT static QBasicMutex mutex;
QMutexLocker locker(&mutex);
if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES)
return;
@@ -137,7 +112,7 @@ void QAdoptedThread::init()
static QList<HANDLE> qt_adopted_thread_handles;
static QList<QThread *> qt_adopted_qthreads;
-static QBasicMutex qt_adopted_thread_watcher_mutex;
+Q_CONSTINIT static QBasicMutex qt_adopted_thread_watcher_mutex;
static DWORD qt_adopted_thread_watcher_id = 0;
static HANDLE qt_adopted_thread_wakeup = 0;
@@ -248,39 +223,6 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
return 0;
}
-#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC)
-
-#ifndef Q_OS_WIN64
-# define ULONG_PTR DWORD
-#endif
-
-typedef struct tagTHREADNAME_INFO
-{
- DWORD dwType; // must be 0x1000
- LPCSTR szName; // pointer to name (in user addr space)
- HANDLE dwThreadID; // thread ID (-1=caller thread)
- DWORD dwFlags; // reserved for future use, must be zero
-} THREADNAME_INFO;
-
-void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
-{
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = threadName;
- info.dwThreadID = threadId;
- info.dwFlags = 0;
-
- __try
- {
- RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD),
- reinterpret_cast<const ULONG_PTR*>(&info));
- }
- __except (EXCEPTION_CONTINUE_EXECUTION)
- {
- }
-}
-#endif // !QT_NO_DEBUG && Q_CC_MSVC
-
/**************************************************************************
** QThreadPrivate
*************************************************************************/
@@ -314,13 +256,11 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
data->ensureEventDispatcher();
data->eventDispatcher.loadRelaxed()->startingUp();
-#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC)
// sets the name of the current thread.
- QByteArray objectName = thr->objectName().toLocal8Bit();
- qt_set_thread_name(HANDLE(-1),
- objectName.isEmpty() ?
- thr->metaObject()->className() : objectName.constData());
-#endif
+ QString threadName = std::exchange(thr->d_func()->objectName, {});
+ if (Q_LIKELY(threadName.isEmpty()))
+ threadName = QString::fromUtf8(thr->metaObject()->className());
+ SetThreadDescription(GetCurrentThread(), reinterpret_cast<const wchar_t *>(threadName.utf16()));
emit thr->started(QThread::QPrivateSignal());
QThread::setTerminationEnabled(true);
@@ -330,28 +270,44 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
return 0;
}
+/*
+ For regularly terminating threads, this will be called and executed by the thread as the
+ last code before the thread exits. In that case, \a arg is the current QThread.
+
+ However, this function will also be called by QThread::terminate (as well as wait() and
+ setTerminationEnabled) to give Qt a chance to update the terminated thread's state and
+ process pending DeleteLater events for objects that live in the terminated thread. And for
+ adopted thread, this method is called by the thread watcher.
+
+ In those cases, \a arg will not be the current thread.
+*/
void QThreadPrivate::finish(void *arg, bool lockAnyway) noexcept
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadPrivate *d = thr->d_func();
- QMutexLocker locker(lockAnyway ? &d->mutex : 0);
+ QMutexLocker locker(lockAnyway ? &d->mutex : nullptr);
d->isInFinish = true;
d->priority = QThread::InheritPriority;
void **tls_data = reinterpret_cast<void **>(&d->data->tls);
- locker.unlock();
+ if (lockAnyway)
+ locker.unlock();
emit thr->finished(QThread::QPrivateSignal());
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ qCDebug(lcDeleteLater) << "Sending deferred delete events as part of finishing thread" << thr;
+ QCoreApplicationPrivate::sendPostedEvents(nullptr, QEvent::DeferredDelete, d->data);
QThreadStorageData::finish(tls_data);
- locker.relock();
+ if (lockAnyway)
+ locker.relock();
QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
d->data->eventDispatcher = 0;
- locker.unlock();
+ if (lockAnyway)
+ locker.unlock();
eventDispatcher->closingDown();
delete eventDispatcher;
- locker.relock();
+ if (lockAnyway)
+ locker.relock();
}
d->running = false;
@@ -390,6 +346,12 @@ void QThread::yieldCurrentThread()
#endif // QT_CONFIG(thread)
+void QThread::sleep(std::chrono::nanoseconds nsecs)
+{
+ using namespace std::chrono;
+ ::Sleep(DWORD(duration_cast<milliseconds>(nsecs).count()));
+}
+
void QThread::sleep(unsigned long secs)
{
::Sleep(secs * 1000);
@@ -421,6 +383,9 @@ void QThread::start(Priority priority)
if (d->running)
return;
+ // avoid interacting with the binding system
+ d->objectName = d->extraData ? d->extraData->objectName.valueBypassingBindings()
+ : QString();
d->running = true;
d->finished = false;
d->exited = false;
@@ -457,7 +422,7 @@ void QThread::start(Priority priority)
int prio;
d->priority = priority;
- switch (d->priority) {
+ switch (priority) {
case IdlePriority:
prio = THREAD_PRIORITY_IDLE;
break;
@@ -584,7 +549,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
int prio;
priority = threadPriority;
- switch (priority) {
+ switch (threadPriority) {
case QThread::IdlePriority:
prio = THREAD_PRIORITY_IDLE;
break;