48 #include <private/qcoreapplication_p.h>
49 #include <private/qeventdispatcher_win_p.h>
62 void qt_watch_adopted_thread(
const HANDLE adoptedThreadHandle,
QThread *qthread);
63 DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID);
65 static DWORD qt_current_thread_data_tls_index = TLS_OUT_OF_INDEXES;
68 if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES)
72 if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES)
74 qt_current_thread_data_tls_index = TlsAlloc();
77 static void qt_free_tls()
79 if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES) {
80 TlsFree(qt_current_thread_data_tls_index);
81 qt_current_thread_data_tls_index = TLS_OUT_OF_INDEXES;
84 Q_DESTRUCTOR_FUNCTION(qt_free_tls)
91 TlsSetValue(qt_current_thread_data_tls_index, 0);
98 if (!threadData && createIfNecessary) {
102 TlsSetValue(qt_current_thread_data_tls_index, threadData);
106 TlsSetValue(qt_current_thread_data_tls_index, 0);
118 HANDLE realHandle = INVALID_HANDLE_VALUE;
119 DuplicateHandle(GetCurrentProcess(),
125 DUPLICATE_SAME_ACCESS);
126 qt_watch_adopted_thread(realHandle, threadData->
thread);
134 d_func()->handle = GetCurrentThread();
135 d_func()->id = GetCurrentThreadId();
140 static QBasicMutex qt_adopted_thread_watcher_mutex;
141 static DWORD qt_adopted_thread_watcher_id = 0;
142 static HANDLE qt_adopted_thread_wakeup = 0;
150 void qt_watch_adopted_thread(
const HANDLE adoptedThreadHandle,
QThread *qthread)
154 if (GetCurrentThreadId() == qt_adopted_thread_watcher_id) {
155 CloseHandle(adoptedThreadHandle);
159 qt_adopted_thread_handles.
append(adoptedThreadHandle);
160 qt_adopted_qthreads.
append(qthread);
163 if (qt_adopted_thread_watcher_id == 0) {
164 if (qt_adopted_thread_wakeup == 0) {
165 qt_adopted_thread_wakeup = CreateEvent(0,
false,
false, 0);
166 qt_adopted_thread_handles.
prepend(qt_adopted_thread_wakeup);
169 CloseHandle(CreateThread(0, 0, qt_adopted_thread_watcher_function, 0, 0, &qt_adopted_thread_watcher_id));
171 SetEvent(qt_adopted_thread_wakeup);
180 DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
183 qt_adopted_thread_watcher_mutex.
lock();
185 if (qt_adopted_thread_handles.
count() == 1) {
186 qt_adopted_thread_watcher_id = 0;
187 qt_adopted_thread_watcher_mutex.
unlock();
192 qt_adopted_thread_watcher_mutex.
unlock();
194 DWORD
ret = WAIT_TIMEOUT;
197 int loops = handlesCopy.
size() / MAXIMUM_WAIT_OBJECTS;
198 if (handlesCopy.
size() % MAXIMUM_WAIT_OBJECTS)
204 ret = WaitForMultipleObjects(handlesCopy.
count(), handlesCopy.
constData(),
false, INFINITE);
208 offset = loop * MAXIMUM_WAIT_OBJECTS;
211 loop = (loop + 1) % loops;
212 }
while (
ret == WAIT_TIMEOUT);
216 qWarning(
"QThread internal error while waiting for adopted threads: %d",
int(GetLastError()));
220 const int handleIndex =
offset +
ret - WAIT_OBJECT_0;
221 if (handleIndex == 0)
223 const int qthreadIndex = handleIndex - 1;
225 qt_adopted_thread_watcher_mutex.
lock();
227 qt_adopted_thread_watcher_mutex.
unlock();
228 if (
data->isAdopted) {
234 QThreadPrivate::finish(thread);
239 CloseHandle(qt_adopted_thread_handles.
at(handleIndex));
240 qt_adopted_thread_handles.
remove(handleIndex);
241 qt_adopted_qthreads.
remove(qthreadIndex);
251 #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC)
254 # define ULONG_PTR DWORD
257 typedef struct tagTHREADNAME_INFO
265 void qt_set_thread_name(
HANDLE threadId, LPCSTR threadName)
267 THREADNAME_INFO
info;
268 info.dwType = 0x1000;
269 info.szName = threadName;
270 info.dwThreadID = threadId;
275 RaiseException(0x406D1388, 0,
sizeof(
info)/
sizeof(DWORD),
276 reinterpret_cast<const ULONG_PTR*
>(&
info));
278 __except (EXCEPTION_CONTINUE_EXECUTION)
296 #if QT_CONFIG(thread)
304 TlsSetValue(qt_current_thread_data_tls_index,
data);
311 data->quitNow = thr->d_func()->exited;
314 data->ensureEventDispatcher();
317 #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC)
320 ? thr->metaObject()->className()
321 : std::exchange(thr->d_func()->
objectName, {}).toLocal8Bit().constData());
332 void QThreadPrivate::finish(
void *
arg,
bool lockAnyway) noexcept
338 d->isInFinish =
true;
340 void **tls_data =
reinterpret_cast<void **
>(&
d->data->tls);
344 QThreadStorageData::finish(tls_data);
348 if (eventDispatcher) {
349 d->data->eventDispatcher = 0;
352 delete eventDispatcher;
358 d->isInFinish =
false;
359 d->interruptionRequested =
false;
362 CloseHandle(
d->handle);
373 Qt::HANDLE QThread::currentThreadIdImpl() noexcept
381 GetSystemInfo(&sysinfo);
382 return sysinfo.dwNumberOfProcessors;
394 ::Sleep(secs * 1000);
404 ::Sleep((usecs / 1000) + 1);
407 #if QT_CONFIG(thread)
424 d->objectName =
d->extraData ?
d->extraData->objectName.valueBypassingBindings()
430 d->interruptionRequested =
false;
442 #if defined(Q_CC_MSVC) && !defined(_DLL)
445 this, CREATE_SUSPENDED, &(
d->id));
448 d->handle = CreateThread(
nullptr,
d->stackSize,
450 this, CREATE_SUSPENDED,
reinterpret_cast<LPDWORD
>(&
d->id));
464 prio = THREAD_PRIORITY_IDLE;
468 prio = THREAD_PRIORITY_LOWEST;
472 prio = THREAD_PRIORITY_BELOW_NORMAL;
476 prio = THREAD_PRIORITY_NORMAL;
480 prio = THREAD_PRIORITY_ABOVE_NORMAL;
484 prio = THREAD_PRIORITY_HIGHEST;
488 prio = THREAD_PRIORITY_TIME_CRITICAL;
493 prio = GetThreadPriority(GetCurrentThread());
497 if (!SetThreadPriority(
d->handle, prio)) {
498 qErrnoWarning(
"QThread::start: Failed to set thread priority");
501 if (ResumeThread(
d->handle) == (DWORD) -1) {
502 qErrnoWarning(
"QThread::start: Failed to resume new thread");
512 if (!
d->terminationEnabled) {
513 d->terminatePending =
true;
517 TerminateThread(
d->handle, 0);
518 QThreadPrivate::finish(
this,
false);
526 if (
d->id == GetCurrentThreadId()) {
527 qWarning(
"QThread::wait: Thread tried to wait on itself");
530 if (
d->finished || !
d->running)
534 locker.mutex()->unlock();
550 locker.mutex()->lock();
553 if (
ret && !
d->finished) {
556 QThreadPrivate::finish(
this,
false);
559 if (
d->finished && !
d->waiters) {
560 CloseHandle(
d->handle);
570 Q_ASSERT_X(thr != 0,
"QThread::setTerminationEnabled()",
571 "Current thread was not started with QThread.");
575 if (
enabled &&
d->terminatePending) {
576 QThreadPrivate::finish(thr,
false);
588 priority = threadPriority;
589 switch (threadPriority) {
591 prio = THREAD_PRIORITY_IDLE;
595 prio = THREAD_PRIORITY_LOWEST;
599 prio = THREAD_PRIORITY_BELOW_NORMAL;
603 prio = THREAD_PRIORITY_NORMAL;
607 prio = THREAD_PRIORITY_ABOVE_NORMAL;
611 prio = THREAD_PRIORITY_HIGHEST;
615 prio = THREAD_PRIORITY_TIME_CRITICAL;
622 if (!SetThreadPriority(
handle, prio)) {
623 qErrnoWarning(
"QThread::setPriority: Failed to set thread priority");
The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
virtual void startingUp()
virtual void closingDown()
Type loadRelaxed() const noexcept
void storeRelaxed(Type newValue) noexcept
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
static QBasicAtomicPointer< QThread > theMainThread
The QDeadlineTimer class marks a deadline in the future.
qint64 remainingTime() const noexcept
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)
The QMutex class provides access serialization between threads.
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes.
QString objectName
the name of this object
static QObjectPrivate * get(QObject *o)
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
QThreadData(int initialRefCount=1)
static QThreadData * get2(QThread *thread)
static void clearCurrentThreadData()
QAtomicPointer< void > threadId
QAtomicPointer< QThread > thread
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)
static QAbstractEventDispatcher * createEventDispatcher(QThreadData *data)
myinstance setPriority(MyClass::VeryHigh)
backing_store_ptr info
[4]
Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void qErrnoWarning(int code, const char *msg,...)
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)
QDeadlineTimer deadline(30s)