8#include <private/qcoreapplication_p.h>
9#include <private/qeventdispatcher_win_p.h>
14#include <qt_windows.h>
28 _In_ PCWSTR lpThreadDescription
32#ifndef THREAD_POWER_THROTTLING_EXECUTION_SPEED
33#define THREAD_POWER_THROTTLING_EXECUTION_SPEED 0x1
34#define THREAD_POWER_THROTTLING_CURRENT_VERSION 1
40} THREAD_POWER_THROTTLING_STATE;
50Q_CONSTINIT
static thread_local QThreadData *currentThreadData =
nullptr;
52static void destroy_current_thread_data(
void *p)
54 QThreadData *data =
static_cast<QThreadData *>(p);
55 QThread *thread = data->thread.loadAcquire();
57 if (data->isAdopted) {
61 QThreadPrivate *thread_p =
static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
73 currentThreadData =
nullptr;
76static QThreadData *get_thread_data()
78 return currentThreadData;
81static void set_thread_data(QThreadData *data)
noexcept
85 ~Cleanup() { destroy_current_thread_data(currentThreadData); }
87 static thread_local Cleanup currentThreadCleanup;
89 currentThreadData = data;
93
94
95void QThreadData::clearCurrentThreadData()
97 set_thread_data(
nullptr);
100QThreadData *QThreadData::currentThreadData()
noexcept
102 return get_thread_data();
105QThreadData *QThreadData::createCurrentThreadData()
107 Q_ASSERT(!currentThreadData());
108 std::unique_ptr data = std::make_unique<QThreadData>();
112 set_thread_data(data.get());
115 data->thread.storeRelease(
new QAdoptedThread(data.get()));
117 clearCurrentThreadData();
120 return data.release();
123void QAdoptedThread::init()
125 d_func()->handle = GetCurrentThread();
129
130
137 return new QEventDispatcherWin32;
142unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(
void *arg)
noexcept
144 QThread *thr =
reinterpret_cast<QThread *>(arg);
145 QThreadData *data = QThreadData::get2(thr);
148 set_thread_data(data);
149 data->threadId.storeRelaxed(QThread::currentThreadId());
151 QThread::setTerminationEnabled(
false);
154 QMutexLocker locker(&thr->d_func()->mutex);
155 data->quitNow = thr->d_func()->exited;
157 if (thr->d_func()->serviceLevel != QThread::QualityOfService::Auto)
158 thr->d_func()->setQualityOfServiceLevel(thr->d_func()->serviceLevel);
161 data->ensureEventDispatcher();
162 data->eventDispatcher.loadRelaxed()->startingUp();
165 QString threadName = std::exchange(thr->d_func()->objectName, {});
166 if (Q_LIKELY(threadName.isEmpty()))
167 threadName = QString::fromUtf8(thr->metaObject()->className());
168 SetThreadDescription(GetCurrentThread(),
reinterpret_cast<
const wchar_t *>(threadName.utf16()));
170 emit thr->started(QThread::QPrivateSignal());
171 QThread::setTerminationEnabled(
true);
174 thr->d_func()->finish();
178void QThreadPrivate::setQualityOfServiceLevel(QThread::QualityOfService qosLevel)
181 serviceLevel = qosLevel;
183#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10_RS3)
184 qCDebug(lcQThread) <<
"Setting thread QoS class to" << qosLevel <<
"for thread" << q;
186 THREAD_POWER_THROTTLING_STATE state;
187 memset(&state, 0,
sizeof(state));
188 state.Version = THREAD_POWER_THROTTLING_CURRENT_VERSION;
191 case QThread::QualityOfService::Auto:
192 state.ControlMask = 0;
195 case QThread::QualityOfService::Eco:
196 state.ControlMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED;
197 state.StateMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED;
199 case QThread::QualityOfService::High:
200 state.ControlMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED;
204 if (!SetThreadInformation(::GetCurrentThread(), THREAD_INFORMATION_CLASS::ThreadPowerThrottling,
205 &state,
sizeof(state))) {
206 qErrnoWarning(
"Failed to set thread power throttling state");
212
213
214
215
216
217
218
219
220
221
222void QThreadPrivate::finish(
bool lockAnyway)
noexcept
224 QThreadPrivate *d =
this;
225 QThread *thr = q_func();
227 QMutexLocker locker(lockAnyway ? &d->mutex :
nullptr);
228 d->threadState = QThreadPrivate::Finishing;
229 d->priority = QThread::InheritPriority;
230 void **tls_data =
reinterpret_cast<
void **>(&d->data->tls);
233 emit thr->finished(QThread::QPrivateSignal());
234 QCoreApplicationPrivate::sendPostedEvents(
nullptr, QEvent::DeferredDelete, d->data);
235 QThreadStorageData::finish(tls_data);
239 QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.loadRelaxed();
240 if (eventDispatcher) {
241 d->data->eventDispatcher = 0;
244 eventDispatcher->closingDown();
245 delete eventDispatcher;
250 d->threadState = QThreadPrivate::Finished;
251 d->interruptionRequested.store(
false, std::memory_order_relaxed);
254 CloseHandle(d->handle);
260
261
263Qt::HANDLE QThread::currentThreadIdImpl()
noexcept
265 return reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
268int QThread::idealThreadCount()
noexcept
271 GetSystemInfo(&sysinfo);
272 return sysinfo.dwNumberOfProcessors;
275void QThread::yieldCurrentThread()
282void QThread::sleep(std::chrono::nanoseconds nsecs)
284 using namespace std::chrono;
285 ::Sleep(DWORD(duration_cast<milliseconds>(nsecs).count()));
288void QThread::sleep(
unsigned long secs)
290 ::Sleep(secs * 1000);
293void QThread::msleep(
unsigned long msecs)
298void QThread::usleep(
unsigned long usecs)
300 ::Sleep((usecs / 1000) + 1);
305void QThread::start(Priority priority)
308 QMutexLocker locker(&d->mutex);
310 if (d->threadState == QThreadPrivate::Finishing) {
316 if (d->threadState == QThreadPrivate::Running)
320 d->objectName = d->extraData ? d->extraData->objectName.valueBypassingBindings()
322 d->threadState = QThreadPrivate::Running;
325 d->interruptionRequested.store(
false, std::memory_order_relaxed);
328
329
330
331
332
333
334
335
336
337#if defined(Q_CC_MSVC) && !defined(_DLL)
339 d->handle = (Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start,
340 this, CREATE_SUSPENDED,
nullptr);
343 d->handle = CreateThread(
nullptr, d->stackSize,
344 reinterpret_cast<LPTHREAD_START_ROUTINE>(QThreadPrivate::start),
345 this, CREATE_SUSPENDED,
nullptr);
349 qErrnoWarning(
"QThread::start: Failed to create thread");
350 d->threadState = QThreadPrivate::NotStarted;
355 d->priority = priority;
358 prio = THREAD_PRIORITY_IDLE;
362 prio = THREAD_PRIORITY_LOWEST;
366 prio = THREAD_PRIORITY_BELOW_NORMAL;
370 prio = THREAD_PRIORITY_NORMAL;
374 prio = THREAD_PRIORITY_ABOVE_NORMAL;
377 case HighestPriority:
378 prio = THREAD_PRIORITY_HIGHEST;
381 case TimeCriticalPriority:
382 prio = THREAD_PRIORITY_TIME_CRITICAL;
385 case InheritPriority:
387 prio = GetThreadPriority(GetCurrentThread());
391 if (!SetThreadPriority(d->handle, prio)) {
392 qErrnoWarning(
"QThread::start: Failed to set thread priority");
395 if (ResumeThread(d->handle) == (DWORD) -1) {
396 qErrnoWarning(
"QThread::start: Failed to resume new thread");
400void QThread::terminate()
403 QMutexLocker locker(&d->mutex);
404 if (d->threadState != QThreadPrivate::Running)
406 if (!d->terminationEnabled) {
407 d->terminatePending =
true;
411 TerminateThread(d->handle, 0);
415bool QThreadPrivate::wait(QMutexLocker<QMutex> &locker, QDeadlineTimer deadline)
417 Q_ASSERT(threadState != QThreadPrivate::Finished);
418 Q_ASSERT(locker.isLocked());
419 QThreadPrivate *d =
this;
422 locker.mutex()->unlock();
425 switch (WaitForSingleObject(d->handle, deadline.remainingTime())) {
430 qErrnoWarning(
"QThread::wait: Thread wait failure");
438 locker.mutex()->lock();
441 if (ret && d->threadState < QThreadPrivate::Finished) {
447 if (d->threadState == QThreadPrivate::Finished && !d->waiters) {
448 CloseHandle(d->handle);
455void QThread::setTerminationEnabled(
bool enabled)
457 QThread *thr = currentThread();
458 Q_ASSERT_X(thr != 0,
"QThread::setTerminationEnabled()",
459 "Current thread was not started with QThread.");
460 QThreadPrivate *d = thr->d_func();
461 QMutexLocker locker(&d->mutex);
462 d->terminationEnabled = enabled;
463 if (enabled && d->terminatePending) {
471void QThreadPrivate::setPriority(QThread::Priority threadPriority)
476 priority = threadPriority;
477 switch (threadPriority) {
478 case QThread::IdlePriority:
479 prio = THREAD_PRIORITY_IDLE;
482 case QThread::LowestPriority:
483 prio = THREAD_PRIORITY_LOWEST;
486 case QThread::LowPriority:
487 prio = THREAD_PRIORITY_BELOW_NORMAL;
490 case QThread::NormalPriority:
491 prio = THREAD_PRIORITY_NORMAL;
494 case QThread::HighPriority:
495 prio = THREAD_PRIORITY_ABOVE_NORMAL;
498 case QThread::HighestPriority:
499 prio = THREAD_PRIORITY_HIGHEST;
502 case QThread::TimeCriticalPriority:
503 prio = THREAD_PRIORITY_TIME_CRITICAL;
510 if (!SetThreadPriority(handle, prio)) {
511 qErrnoWarning(
"QThread::setPriority: Failed to set thread priority");
static QAbstractEventDispatcher * createEventDispatcher(QThreadData *data)
#define Q_STATIC_LOGGING_CATEGORY(name,...)