12#include <private/qcoreapplication_p.h>
13#include <private/qeventdispatcher_win_p.h>
26void qt_watch_adopted_thread(
const HANDLE adoptedThreadHandle,
QThread *qthread);
27DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID);
29static DWORD qt_current_thread_data_tls_index = TLS_OUT_OF_INDEXES;
32 if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES)
36 if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES)
38 qt_current_thread_data_tls_index = TlsAlloc();
41static void qt_free_tls()
43 if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES) {
44 TlsFree(qt_current_thread_data_tls_index);
45 qt_current_thread_data_tls_index = TLS_OUT_OF_INDEXES;
48Q_DESTRUCTOR_FUNCTION(qt_free_tls)
55 TlsSetValue(qt_current_thread_data_tls_index, 0);
62 if (!threadData && createIfNecessary) {
66 TlsSetValue(qt_current_thread_data_tls_index, threadData);
70 TlsSetValue(qt_current_thread_data_tls_index, 0);
82 HANDLE realHandle = INVALID_HANDLE_VALUE;
83 DuplicateHandle(GetCurrentProcess(),
89 DUPLICATE_SAME_ACCESS);
90 qt_watch_adopted_thread(realHandle, threadData->
thread);
98 d_func()->handle = GetCurrentThread();
99 d_func()->id = GetCurrentThreadId();
104Q_CONSTINIT
static QBasicMutex qt_adopted_thread_watcher_mutex;
105static DWORD qt_adopted_thread_watcher_id = 0;
106static HANDLE qt_adopted_thread_wakeup = 0;
114void qt_watch_adopted_thread(
const HANDLE adoptedThreadHandle,
QThread *qthread)
118 if (GetCurrentThreadId() == qt_adopted_thread_watcher_id) {
119 CloseHandle(adoptedThreadHandle);
123 qt_adopted_thread_handles.
append(adoptedThreadHandle);
124 qt_adopted_qthreads.
append(qthread);
127 if (qt_adopted_thread_watcher_id == 0) {
128 if (qt_adopted_thread_wakeup == 0) {
129 qt_adopted_thread_wakeup = CreateEvent(0,
false,
false, 0);
130 qt_adopted_thread_handles.
prepend(qt_adopted_thread_wakeup);
133 CloseHandle(CreateThread(0, 0, qt_adopted_thread_watcher_function, 0, 0, &qt_adopted_thread_watcher_id));
135 SetEvent(qt_adopted_thread_wakeup);
144DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
147 qt_adopted_thread_watcher_mutex.lock();
149 if (qt_adopted_thread_handles.
count() == 1) {
150 qt_adopted_thread_watcher_id = 0;
151 qt_adopted_thread_watcher_mutex.unlock();
156 qt_adopted_thread_watcher_mutex.unlock();
158 DWORD
ret = WAIT_TIMEOUT;
161 int loops = handlesCopy.
size() / MAXIMUM_WAIT_OBJECTS;
162 if (handlesCopy.
size() % MAXIMUM_WAIT_OBJECTS)
168 ret = WaitForMultipleObjects(handlesCopy.
count(), handlesCopy.
constData(),
false, INFINITE);
172 offset = loop * MAXIMUM_WAIT_OBJECTS;
175 loop = (loop + 1) % loops;
176 }
while (
ret == WAIT_TIMEOUT);
180 qWarning(
"QThread internal error while waiting for adopted threads: %d",
int(GetLastError()));
184 const int handleIndex =
offset +
ret - WAIT_OBJECT_0;
185 if (handleIndex == 0)
187 const int qthreadIndex = handleIndex - 1;
189 qt_adopted_thread_watcher_mutex.lock();
191 qt_adopted_thread_watcher_mutex.unlock();
192 if (
data->isAdopted) {
198 QThreadPrivate::finish(thread);
203 CloseHandle(qt_adopted_thread_handles.
at(handleIndex));
204 qt_adopted_thread_handles.
remove(handleIndex);
205 qt_adopted_qthreads.
remove(qthreadIndex);
215#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC)
218# define ULONG_PTR DWORD
221typedef struct tagTHREADNAME_INFO
229void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
231 THREADNAME_INFO
info;
232 info.dwType = 0x1000;
233 info.szName = threadName;
234 info.dwThreadID = threadId;
239 RaiseException(0x406D1388, 0,
sizeof(
info)/
sizeof(DWORD),
240 reinterpret_cast<const ULONG_PTR*
>(&
info));
242 __except (EXCEPTION_CONTINUE_EXECUTION)
262unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(
void *
arg)
noexcept
268 TlsSetValue(qt_current_thread_data_tls_index,
data);
275 data->quitNow = thr->d_func()->exited;
278 data->ensureEventDispatcher();
281#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC)
284 ? thr->metaObject()->className()
285 :
std::exchange(thr->d_func()->objectName, {}).
toLocal8Bit().constData());
307void QThreadPrivate::finish(
void *
arg,
bool lockAnyway)
noexcept
313 d->isInFinish =
true;
315 void **tls_data =
reinterpret_cast<void **
>(&
d->data->tls);
320 QThreadStorageData::finish(tls_data);
325 if (eventDispatcher) {
326 d->data->eventDispatcher = 0;
330 delete eventDispatcher;
337 d->isInFinish =
false;
338 d->interruptionRequested =
false;
341 CloseHandle(
d->handle);
352Qt::HANDLE QThread::currentThreadIdImpl() noexcept
360 GetSystemInfo(&sysinfo);
361 return sysinfo.dwNumberOfProcessors;
373 using namespace std::chrono;
374 ::Sleep(DWORD(duration_cast<milliseconds>(nsecs).
count()));
379 ::Sleep(secs * 1000);
389 ::Sleep((usecs / 1000) + 1);
409 d->objectName =
d->extraData ?
d->extraData->objectName.valueBypassingBindings()
415 d->interruptionRequested =
false;
427#if defined(Q_CC_MSVC) && !defined(_DLL)
429 d->handle = (
Qt::HANDLE) _beginthreadex(NULL,
d->stackSize, QThreadPrivate::start,
430 this, CREATE_SUSPENDED, &(
d->id));
433 d->handle = CreateThread(
nullptr,
d->stackSize,
434 reinterpret_cast<LPTHREAD_START_ROUTINE
>(QThreadPrivate::start),
435 this, CREATE_SUSPENDED,
reinterpret_cast<LPDWORD
>(&
d->id));
449 prio = THREAD_PRIORITY_IDLE;
453 prio = THREAD_PRIORITY_LOWEST;
457 prio = THREAD_PRIORITY_BELOW_NORMAL;
461 prio = THREAD_PRIORITY_NORMAL;
465 prio = THREAD_PRIORITY_ABOVE_NORMAL;
469 prio = THREAD_PRIORITY_HIGHEST;
473 prio = THREAD_PRIORITY_TIME_CRITICAL;
478 prio = GetThreadPriority(GetCurrentThread());
482 if (!SetThreadPriority(
d->handle, prio)) {
483 qErrnoWarning(
"QThread::start: Failed to set thread priority");
486 if (ResumeThread(
d->handle) == (DWORD) -1) {
487 qErrnoWarning(
"QThread::start: Failed to resume new thread");
497 if (!
d->terminationEnabled) {
498 d->terminatePending =
true;
502 TerminateThread(
d->handle, 0);
503 QThreadPrivate::finish(
this,
false);
511 if (
d->id == GetCurrentThreadId()) {
512 qWarning(
"QThread::wait: Thread tried to wait on itself");
515 if (
d->finished || !
d->running)
519 locker.mutex()->unlock();
535 locker.mutex()->lock();
538 if (
ret && !
d->finished) {
541 QThreadPrivate::finish(
this,
false);
544 if (
d->finished && !
d->waiters) {
545 CloseHandle(
d->handle);
555 Q_ASSERT_X(thr != 0,
"QThread::setTerminationEnabled()",
556 "Current thread was not started with QThread.");
560 if (
enabled &&
d->terminatePending) {
561 QThreadPrivate::finish(thr,
false);
573 priority = threadPriority;
574 switch (threadPriority) {
576 prio = THREAD_PRIORITY_IDLE;
580 prio = THREAD_PRIORITY_LOWEST;
584 prio = THREAD_PRIORITY_BELOW_NORMAL;
588 prio = THREAD_PRIORITY_NORMAL;
592 prio = THREAD_PRIORITY_ABOVE_NORMAL;
596 prio = THREAD_PRIORITY_HIGHEST;
600 prio = THREAD_PRIORITY_TIME_CRITICAL;
607 if (!SetThreadPriority(
handle, prio)) {
608 qErrnoWarning(
"QThread::setPriority: Failed to set thread priority");
virtual void startingUp()
virtual void closingDown()
Type loadRelaxed() const noexcept
void storeRelaxed(Type newValue) noexcept
static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data)
static QBasicAtomicPointer< QThread > theMainThread
qint64 remainingTime() const noexcept
Returns the remaining time in this QDeadlineTimer object in milliseconds.
qsizetype size() const noexcept
const_pointer constData() const noexcept
const_reference at(qsizetype i) const noexcept
void remove(qsizetype i, qsizetype n=1)
qsizetype count() const noexcept
void prepend(rvalue_ref t)
void append(parameter_type t)
static QObjectPrivate * get(QObject *o)
QString objectName
the name of this object
QThread * thread() const
Returns the thread in which the object lives.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
static void clearCurrentThreadData()
QAtomicPointer< void > threadId
static QThreadData * get2(QThread *thread)
QAtomicPointer< QThread > thread
static QAbstractEventDispatcher * createEventDispatcher(QThreadData *data)
void start(Priority=InheritPriority)
QAbstractEventDispatcher * eventDispatcher() const
static int idealThreadCount() noexcept
static void setTerminationEnabled(bool enabled=true)
static QThread * currentThread()
static void yieldCurrentThread()
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
static void usleep(unsigned long)
Priority priority() const
void finished(QPrivateSignal)
static void msleep(unsigned long)
static void sleep(unsigned long)
void started(QPrivateSignal)
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
constexpr const T & qMin(const T &a, const T &b)
GLuint64 GLenum void * handle
GLenum GLenum GLsizei count
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
#define Q_ASSERT_X(cond, x, msg)
static char * toLocal8Bit(char *out, QStringView in, QStringConverter::State *state)
QFileInfo info(fileName)
[8]
QDeadlineTimer deadline(30s)