43 #if _WIN32_WINNT < 0x0400 44 #define _WIN32_WINNT 0x0400 56 #include <private/qcoreapplication_p.h> 57 #include <private/qeventdispatcher_win_p.h> 114 adopted->d_func()->running =
true;
115 adopted->d_func()->finished =
false;
138 HANDLE realHandle = INVALID_HANDLE_VALUE;
139 #if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) 140 DuplicateHandle(GetCurrentProcess(),
146 DUPLICATE_SAME_ACCESS);
148 realHandle =
reinterpret_cast<HANDLE>(GetCurrentThreadId());
158 d_func()->handle = GetCurrentThread();
159 d_func()->id = GetCurrentThreadId();
181 #if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) 182 CloseHandle(adoptedThreadHandle);
187 qt_adopted_thread_handles.
append(adoptedThreadHandle);
188 qt_adopted_qthreads.
append(qthread);
214 qt_adopted_thread_watcher_mutex.
lock();
216 if (qt_adopted_thread_handles.
count() == 1) {
218 qt_adopted_thread_watcher_mutex.
unlock();
223 qt_adopted_thread_watcher_mutex.
unlock();
225 DWORD ret = WAIT_TIMEOUT;
228 int loops = handlesCopy.
size() / MAXIMUM_WAIT_OBJECTS;
229 if (handlesCopy.
size() % MAXIMUM_WAIT_OBJECTS)
234 count = handlesCopy.
count();
235 ret = WaitForMultipleObjects(handlesCopy.
count(), handlesCopy.
constData(),
false, INFINITE);
239 offset = loop * MAXIMUM_WAIT_OBJECTS;
240 count =
qMin(handlesCopy.
count() - offset, MAXIMUM_WAIT_OBJECTS);
241 ret = WaitForMultipleObjects(count, handlesCopy.
constData() + offset,
false, 100);
242 loop = (loop + 1) % loops;
243 }
while (ret == WAIT_TIMEOUT);
247 qWarning(
"QThread internal error while waiting for adopted threads: %d",
int(GetLastError()));
252 if (handleIndex == 0){
257 const int qthreadIndex = handleIndex - 1;
259 qt_adopted_thread_watcher_mutex.
lock();
261 qt_adopted_thread_watcher_mutex.
unlock();
272 #if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) 273 CloseHandle(qt_adopted_thread_handles.
at(handleIndex));
275 qt_adopted_thread_handles.
remove(handleIndex);
276 qt_adopted_qthreads.
remove(qthreadIndex);
287 #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) 290 # define ULONG_PTR DWORD 293 typedef struct tagTHREADNAME_INFO
303 THREADNAME_INFO
info;
304 info.dwType = 0x1000;
305 info.szName = threadName;
311 RaiseException(0x406D1388, 0,
sizeof(info)/
sizeof(DWORD), (
const ULONG_PTR*)&info);
313 __except (EXCEPTION_CONTINUE_EXECUTION)
317 #endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE 323 #endif // QT_NO_THREAD 346 data->
quitNow = thr->d_func()->exited;
349 createEventDispatcher(data);
351 #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) 354 qt_set_thread_name((
HANDLE)-1,
376 void **tls_data =
reinterpret_cast<void **
>(&d->
data->
tls);
388 if (eventDispatcher) {
415 return reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
421 GetSystemInfo(&sysinfo);
422 return sysinfo.dwNumberOfProcessors;
436 ::Sleep(secs * 1000);
446 ::Sleep((usecs / 1000) + 1);
466 d->terminated =
false;
481 this, CREATE_SUSPENDED, &(
d->id));
491 d->priority = priority;
492 switch (
d->priority) {
494 prio = THREAD_PRIORITY_IDLE;
498 prio = THREAD_PRIORITY_LOWEST;
502 prio = THREAD_PRIORITY_BELOW_NORMAL;
506 prio = THREAD_PRIORITY_NORMAL;
510 prio = THREAD_PRIORITY_ABOVE_NORMAL;
513 case HighestPriority:
514 prio = THREAD_PRIORITY_HIGHEST;
517 case TimeCriticalPriority:
518 prio = THREAD_PRIORITY_TIME_CRITICAL;
521 case InheritPriority:
523 prio = GetThreadPriority(GetCurrentThread());
527 if (!SetThreadPriority(
d->handle, prio)) {
528 qErrnoWarning(
"QThread::start: Failed to set thread priority");
531 if (ResumeThread(
d->handle) == (DWORD) -1) {
532 qErrnoWarning(
"QThread::start: Failed to resume new thread");
542 if (!
d->terminationEnabled) {
543 d->terminatePending =
true;
546 TerminateThread(
d->handle, 0);
547 d->terminated =
true;
556 if (
d->id == GetCurrentThreadId()) {
557 qWarning(
"QThread::wait: Thread tried to wait on itself");
560 if (
d->finished || !
d->running)
567 switch (WaitForSingleObject(
d->handle, time)) {
583 if (ret && !
d->finished) {
585 d->terminated =
true;
589 if (
d->finished && !
d->waiters) {
590 CloseHandle(
d->handle);
599 QThread *thr = currentThread();
600 Q_ASSERT_X(thr != 0,
"QThread::setTerminationEnabled()",
601 "Current thread was not started with QThread.");
618 qWarning(
"QThread::setPriority: Cannot set priority, thread is not running");
625 d->priority = priority;
626 switch (
d->priority) {
628 prio = THREAD_PRIORITY_IDLE;
632 prio = THREAD_PRIORITY_LOWEST;
636 prio = THREAD_PRIORITY_BELOW_NORMAL;
640 prio = THREAD_PRIORITY_NORMAL;
644 prio = THREAD_PRIORITY_ABOVE_NORMAL;
647 case HighestPriority:
648 prio = THREAD_PRIORITY_HIGHEST;
651 case TimeCriticalPriority:
652 prio = THREAD_PRIORITY_TIME_CRITICAL;
655 case InheritPriority:
657 qWarning(
"QThread::setPriority: Argument cannot be InheritPriority");
661 if (!SetThreadPriority(
d->handle, prio)) {
662 qErrnoWarning(
"QThread::setPriority: Failed to set thread priority");
667 #endif // QT_NO_THREAD
virtual void run()
The starting point for the thread.
virtual void startingUp()
static mach_timebase_info_data_t info
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
static void finish(void **)
#define QT_END_NAMESPACE
This macro expands to.
void lock()
Locks the mutex.
The QMutex class provides access serialization between threads.
void remove(int i)
Removes the element at index position i.
int count(const T &t) const
Returns the number of occurrences of value in the vector.
The QByteArray class provides an array of bytes.
static void * start(void *arg)
void finished()
This signal is emitted when the thread has finished executing.
void unlock()
Unlocks this mutex locker.
static void qt_free_tls()
#define _beginthreadex(a, b, c, d, e, f)
static QThread * theMainThread
static void clearCurrentThreadData()
void started()
This signal is emitted when the thread starts executing.
static DWORD qt_current_thread_data_tls_index
#define Q_DESTRUCTOR_FUNCTION(AFUNC)
static QMutex qt_adopted_thread_watcher_mutex
DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
This function loops and waits for native adopted threads to finish.
static QObjectPrivate * get(QObject *o)
#define QT_ENSURE_STACK_ALIGNED_FOR_SSE
static void yieldCurrentThread()
Yields execution of the current thread to another runnable thread, if any.
void relock()
Relocks an unlocked mutex locker.
static void msleep(unsigned long)
Forces the current thread to sleep for msecs milliseconds.
static QThreadData * get2(QThread *thread)
#define QT_BEGIN_NAMESPACE
This macro expands to.
QThreadData(int initialRefCount=1)
static bool activateCallbacks(Callback, void **)
void append(const T &t)
Inserts value at the end of the vector.
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
#define FALSE
Synonym for false.
static void sendPostedEvents()
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
static QVector< HANDLE > qt_adopted_thread_handles
void unlock()
Unlocks the mutex.
#define TLS_OUT_OF_INDEXES
const T & at(int i) const
Returns the item at index position i in the vector.
virtual void closingDown()
const char * constData() const
Returns a pointer to the data stored in the byte array.
#define Q_ASSERT_X(cond, where, what)
void qt_create_tls()
Initializes the QThread system.
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
void terminated()
This signal is emitted when the thread is terminated.
static void setTerminationEnabled(bool enabled=true)
Enables or disables termination of the current thread based on the enabled parameter.
void start(Priority=InheritPriority)
Begins execution of the thread by calling run().
bool wait(unsigned long time=ULONG_MAX)
Blocks the thread until either of these conditions is met:
QString objectName() const
static QReadWriteLock lock
static QThreadData * current()
QThread::Priority priority
void terminate()
Terminates the execution of the thread.
static void sleep(unsigned long)
Forces the current thread to sleep for secs seconds.
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
const T * constData() const
Returns a const pointer to the data stored in the vector.
static void finish(void *)
static HANDLE qt_adopted_thread_wakeup
static void createEventDispatcher(QThreadData *data)
void prepend(const T &t)
Inserts value at the beginning of the vector.
The QThread class provides a platform-independent way to manage threads.
int size() const
Returns the number of items in the vector.
QAbstractEventDispatcher * eventDispatcher
void setPriority(Priority priority)
This function sets the priority for a running thread.
static DWORD qt_adopted_thread_watcher_id
void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread)
Adds an adopted thread to the list of threads that Qt watches to make sure the thread data is properl...
static void usleep(unsigned long)
Forces the current thread to sleep for usecs microseconds.
QMutex * mutex() const
Returns a pointer to the mutex that was locked in the constructor.
The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
virtual const QMetaObject * metaObject() const
Returns a pointer to the meta-object of this object.
static QVector< QThread * > qt_adopted_qthreads
void qErrnoWarning(const char *msg,...)
static Qt::HANDLE currentThreadId()
Returns the thread handle of the currently executing thread.
static int idealThreadCount()
Returns the ideal number of threads that can be run on the system.
#define forever
This macro is provided for convenience for writing infinite loops.