Qt 4.8
qthread_win.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 //#define WINVER 0x0500
43 #if _WIN32_WINNT < 0x0400
44 #define _WIN32_WINNT 0x0400
45 #endif
46 
47 
48 #include "qthread.h"
49 #include "qthread_p.h"
50 #include "qthreadstorage.h"
51 #include "qmutex.h"
52 
53 #include <qcoreapplication.h>
54 #include <qpointer.h>
55 
56 #include <private/qcoreapplication_p.h>
57 #include <private/qeventdispatcher_win_p.h>
58 
59 #include <qt_windows.h>
60 
61 
62 #ifndef Q_OS_WINCE
63 #ifndef _MT
64 #define _MT
65 #endif
66 #include <process.h>
67 #else
68 #include "qfunctions_wince.h"
69 #endif
70 
71 #ifndef QT_NO_THREAD
73 
74 void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread);
75 DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID);
76 
79 {
81  return;
82  static QMutex mutex;
83  QMutexLocker locker(&mutex);
85 }
86 
87 static void qt_free_tls()
88 {
92  }
93 }
95 
96 /*
97  QThreadData
98 */
100 {
101  TlsSetValue(qt_current_thread_data_tls_index, 0);
102 }
103 
105 {
106  qt_create_tls();
107  QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
108  if (!threadData) {
109  QThread *adopted = 0;
111  Q_ASSERT(adopted);
112  threadData = QThreadData::get2(adopted);
113  TlsSetValue(qt_current_thread_data_tls_index, threadData);
114  adopted->d_func()->running = true;
115  adopted->d_func()->finished = false;
116  static_cast<QAdoptedThread *>(adopted)->init();
117  } else {
118  threadData = new QThreadData;
119  // This needs to be called prior to new AdoptedThread() to
120  // avoid recursion.
121  TlsSetValue(qt_current_thread_data_tls_index, threadData);
122  QT_TRY {
123  threadData->thread = new QAdoptedThread(threadData);
124  } QT_CATCH(...) {
125  TlsSetValue(qt_current_thread_data_tls_index, 0);
126  threadData->deref();
127  threadData = 0;
128  QT_RETHROW;
129  }
130  threadData->deref();
131  }
132  threadData->isAdopted = true;
133  threadData->threadId = reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
134 
137  } else {
138  HANDLE realHandle = INVALID_HANDLE_VALUE;
139 #if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600))
140  DuplicateHandle(GetCurrentProcess(),
141  GetCurrentThread(),
142  GetCurrentProcess(),
143  &realHandle,
144  0,
145  FALSE,
146  DUPLICATE_SAME_ACCESS);
147 #else
148  realHandle = reinterpret_cast<HANDLE>(GetCurrentThreadId());
149 #endif
150  qt_watch_adopted_thread(realHandle, threadData->thread);
151  }
152  }
153  return threadData;
154 }
155 
157 {
158  d_func()->handle = GetCurrentThread();
159  d_func()->id = GetCurrentThreadId();
160 }
161 
167 
176 void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread)
177 {
178  QMutexLocker lock(&qt_adopted_thread_watcher_mutex);
179 
180  if (GetCurrentThreadId() == qt_adopted_thread_watcher_id) {
181 #if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600))
182  CloseHandle(adoptedThreadHandle);
183 #endif
184  return;
185  }
186 
187  qt_adopted_thread_handles.append(adoptedThreadHandle);
188  qt_adopted_qthreads.append(qthread);
189 
190  // Start watcher thread if it is not already running.
191  if (qt_adopted_thread_watcher_id == 0) {
192  if (qt_adopted_thread_wakeup == 0) {
193  qt_adopted_thread_wakeup = CreateEvent(0, false, false, 0);
194  qt_adopted_thread_handles.prepend(qt_adopted_thread_wakeup);
195  }
196 
198  } else {
199  SetEvent(qt_adopted_thread_wakeup);
200  }
201 }
202 
212 {
213  forever {
214  qt_adopted_thread_watcher_mutex.lock();
215 
216  if (qt_adopted_thread_handles.count() == 1) {
218  qt_adopted_thread_watcher_mutex.unlock();
219  break;
220  }
221 
223  qt_adopted_thread_watcher_mutex.unlock();
224 
225  DWORD ret = WAIT_TIMEOUT;
226  int count;
227  int offset;
228  int loops = handlesCopy.size() / MAXIMUM_WAIT_OBJECTS;
229  if (handlesCopy.size() % MAXIMUM_WAIT_OBJECTS)
230  ++loops;
231  if (loops == 1) {
232  // no need to loop, no timeout
233  offset = 0;
234  count = handlesCopy.count();
235  ret = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, INFINITE);
236  } else {
237  int loop = 0;
238  do {
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);
244  }
245 
246  if (ret == WAIT_FAILED || ret >= WAIT_OBJECT_0 + uint(count)) {
247  qWarning("QThread internal error while waiting for adopted threads: %d", int(GetLastError()));
248  continue;
249  }
250 
251  const int handleIndex = offset + ret - WAIT_OBJECT_0;
252  if (handleIndex == 0){
253  // New handle to watch was added.
254  continue;
255  } else {
256 // printf("(qt) - qt_adopted_thread_watcher_function... called\n");
257  const int qthreadIndex = handleIndex - 1;
258 
259  qt_adopted_thread_watcher_mutex.lock();
260  QThreadData *data = QThreadData::get2(qt_adopted_qthreads.at(qthreadIndex));
261  qt_adopted_thread_watcher_mutex.unlock();
262  if (data->isAdopted) {
263  QThread *thread = data->thread;
264  Q_ASSERT(thread);
265  QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
266  Q_ASSERT(!thread_p->finished);
267  thread_p->finish(thread);
268  }
269  data->deref();
270 
271  QMutexLocker lock(&qt_adopted_thread_watcher_mutex);
272 #if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600))
273  CloseHandle(qt_adopted_thread_handles.at(handleIndex));
274 #endif
275  qt_adopted_thread_handles.remove(handleIndex);
276  qt_adopted_qthreads.remove(qthreadIndex);
277  }
278  }
279 
280  QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
281  if (threadData)
282  threadData->deref();
283 
284  return 0;
285 }
286 
287 #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)
288 
289 #ifndef Q_OS_WIN64
290 # define ULONG_PTR DWORD
291 #endif
292 
293 typedef struct tagTHREADNAME_INFO
294 {
295  DWORD dwType; // must be 0x1000
296  LPCSTR szName; // pointer to name (in user addr space)
297  HANDLE dwThreadID; // thread ID (-1=caller thread)
298  DWORD dwFlags; // reserved for future use, must be zero
299 } THREADNAME_INFO;
300 
301 void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
302 {
303  THREADNAME_INFO info;
304  info.dwType = 0x1000;
305  info.szName = threadName;
306  info.dwThreadID = threadId;
307  info.dwFlags = 0;
308 
309  __try
310  {
311  RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info);
312  }
313  __except (EXCEPTION_CONTINUE_EXECUTION)
314  {
315  }
316 }
317 #endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE
318 
319 /**************************************************************************
320  ** QThreadPrivate
321  *************************************************************************/
322 
323 #endif // QT_NO_THREAD
324 
326 {
328  data->eventDispatcher->startingUp();
329 }
330 
331 #ifndef QT_NO_THREAD
332 
333 unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg)
334 {
335  QThread *thr = reinterpret_cast<QThread *>(arg);
336  QThreadData *data = QThreadData::get2(thr);
337 
338  qt_create_tls();
339  TlsSetValue(qt_current_thread_data_tls_index, data);
340  data->threadId = reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
341 
343 
344  {
345  QMutexLocker locker(&thr->d_func()->mutex);
346  data->quitNow = thr->d_func()->exited;
347  }
348  // ### TODO: allow the user to create a custom event dispatcher
349  createEventDispatcher(data);
350 
351 #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)
352  // sets the name of the current thread.
353  QByteArray objectName = thr->objectName().toLocal8Bit();
354  qt_set_thread_name((HANDLE)-1,
355  objectName.isEmpty() ?
356  thr->metaObject()->className() : objectName.constData());
357 #endif
358 
359  emit thr->started();
361  thr->run();
362 
363  finish(arg);
364  return 0;
365 }
366 
367 void QThreadPrivate::finish(void *arg, bool lockAnyway)
368 {
369  QThread *thr = reinterpret_cast<QThread *>(arg);
370  QThreadPrivate *d = thr->d_func();
371 
372  QMutexLocker locker(lockAnyway ? &d->mutex : 0);
373  d->isInFinish = true;
375  bool terminated = d->terminated;
376  void **tls_data = reinterpret_cast<void **>(&d->data->tls);
377  locker.unlock();
378  if (terminated)
379  emit thr->terminated();
380  emit thr->finished();
382  QThreadStorageData::finish(tls_data);
383  locker.relock();
384 
385  d->terminated = false;
386 
388  if (eventDispatcher) {
389  d->data->eventDispatcher = 0;
390  locker.unlock();
391  eventDispatcher->closingDown();
392  delete eventDispatcher;
393  locker.relock();
394  }
395 
396  d->running = false;
397  d->finished = true;
398  d->isInFinish = false;
399 
400  if (!d->waiters) {
401  CloseHandle(d->handle);
402  d->handle = 0;
403  }
404 
405  d->id = 0;
406 
407 }
408 
409 /**************************************************************************
410  ** QThread
411  *************************************************************************/
412 
414 {
415  return reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
416 }
417 
419 {
420  SYSTEM_INFO sysinfo;
421  GetSystemInfo(&sysinfo);
422  return sysinfo.dwNumberOfProcessors;
423 }
424 
426 {
427 #ifndef Q_OS_WINCE
428  SwitchToThread();
429 #else
430  ::Sleep(0);
431 #endif
432 }
433 
434 void QThread::sleep(unsigned long secs)
435 {
436  ::Sleep(secs * 1000);
437 }
438 
439 void QThread::msleep(unsigned long msecs)
440 {
441  ::Sleep(msecs);
442 }
443 
444 void QThread::usleep(unsigned long usecs)
445 {
446  ::Sleep((usecs / 1000) + 1);
447 }
448 
449 
450 void QThread::start(Priority priority)
451 {
452  Q_D(QThread);
453  QMutexLocker locker(&d->mutex);
454 
455  if (d->isInFinish) {
456  locker.unlock();
457  wait();
458  locker.relock();
459  }
460 
461  if (d->running)
462  return;
463 
464  d->running = true;
465  d->finished = false;
466  d->terminated = false;
467  d->exited = false;
468  d->returnCode = 0;
469 
470  /*
471  NOTE: we create the thread in the suspended state, set the
472  priority and then resume the thread.
473 
474  since threads are created with normal priority by default, we
475  could get into a case where a thread (with priority less than
476  NormalPriority) tries to create a new thread (also with priority
477  less than NormalPriority), but the newly created thread preempts
478  its 'parent' and runs at normal priority.
479  */
480  d->handle = (Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start,
481  this, CREATE_SUSPENDED, &(d->id));
482 
483  if (!d->handle) {
484  qErrnoWarning(errno, "QThread::start: Failed to create thread");
485  d->running = false;
486  d->finished = true;
487  return;
488  }
489 
490  int prio;
491  d->priority = priority;
492  switch (d->priority) {
493  case IdlePriority:
494  prio = THREAD_PRIORITY_IDLE;
495  break;
496 
497  case LowestPriority:
498  prio = THREAD_PRIORITY_LOWEST;
499  break;
500 
501  case LowPriority:
502  prio = THREAD_PRIORITY_BELOW_NORMAL;
503  break;
504 
505  case NormalPriority:
506  prio = THREAD_PRIORITY_NORMAL;
507  break;
508 
509  case HighPriority:
510  prio = THREAD_PRIORITY_ABOVE_NORMAL;
511  break;
512 
513  case HighestPriority:
514  prio = THREAD_PRIORITY_HIGHEST;
515  break;
516 
517  case TimeCriticalPriority:
518  prio = THREAD_PRIORITY_TIME_CRITICAL;
519  break;
520 
521  case InheritPriority:
522  default:
523  prio = GetThreadPriority(GetCurrentThread());
524  break;
525  }
526 
527  if (!SetThreadPriority(d->handle, prio)) {
528  qErrnoWarning("QThread::start: Failed to set thread priority");
529  }
530 
531  if (ResumeThread(d->handle) == (DWORD) -1) {
532  qErrnoWarning("QThread::start: Failed to resume new thread");
533  }
534 }
535 
536 void QThread::terminate()
537 {
538  Q_D(QThread);
539  QMutexLocker locker(&d->mutex);
540  if (!d->running)
541  return;
542  if (!d->terminationEnabled) {
543  d->terminatePending = true;
544  return;
545  }
546  TerminateThread(d->handle, 0);
547  d->terminated = true;
548  QThreadPrivate::finish(this, false);
549 }
550 
551 bool QThread::wait(unsigned long time)
552 {
553  Q_D(QThread);
554  QMutexLocker locker(&d->mutex);
555 
556  if (d->id == GetCurrentThreadId()) {
557  qWarning("QThread::wait: Thread tried to wait on itself");
558  return false;
559  }
560  if (d->finished || !d->running)
561  return true;
562 
563  ++d->waiters;
564  locker.mutex()->unlock();
565 
566  bool ret = false;
567  switch (WaitForSingleObject(d->handle, time)) {
568  case WAIT_OBJECT_0:
569  ret = true;
570  break;
571  case WAIT_FAILED:
572  qErrnoWarning("QThread::wait: Thread wait failure");
573  break;
574  case WAIT_ABANDONED:
575  case WAIT_TIMEOUT:
576  default:
577  break;
578  }
579 
580  locker.mutex()->lock();
581  --d->waiters;
582 
583  if (ret && !d->finished) {
584  // thread was terminated by someone else
585  d->terminated = true;
586  QThreadPrivate::finish(this, false);
587  }
588 
589  if (d->finished && !d->waiters) {
590  CloseHandle(d->handle);
591  d->handle = 0;
592  }
593 
594  return ret;
595 }
596 
598 {
599  QThread *thr = currentThread();
600  Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()",
601  "Current thread was not started with QThread.");
602  QThreadPrivate *d = thr->d_func();
603  QMutexLocker locker(&d->mutex);
605  if (enabled && d->terminatePending) {
606  d->terminated = true;
607  QThreadPrivate::finish(thr, false);
608  locker.unlock(); // don't leave the mutex locked!
609  _endthreadex(0);
610  }
611 }
612 
613 void QThread::setPriority(Priority priority)
614 {
615  Q_D(QThread);
616  QMutexLocker locker(&d->mutex);
617  if (!d->running) {
618  qWarning("QThread::setPriority: Cannot set priority, thread is not running");
619  return;
620  }
621 
622  // copied from start() with a few modifications:
623 
624  int prio;
625  d->priority = priority;
626  switch (d->priority) {
627  case IdlePriority:
628  prio = THREAD_PRIORITY_IDLE;
629  break;
630 
631  case LowestPriority:
632  prio = THREAD_PRIORITY_LOWEST;
633  break;
634 
635  case LowPriority:
636  prio = THREAD_PRIORITY_BELOW_NORMAL;
637  break;
638 
639  case NormalPriority:
640  prio = THREAD_PRIORITY_NORMAL;
641  break;
642 
643  case HighPriority:
644  prio = THREAD_PRIORITY_ABOVE_NORMAL;
645  break;
646 
647  case HighestPriority:
648  prio = THREAD_PRIORITY_HIGHEST;
649  break;
650 
651  case TimeCriticalPriority:
652  prio = THREAD_PRIORITY_TIME_CRITICAL;
653  break;
654 
655  case InheritPriority:
656  default:
657  qWarning("QThread::setPriority: Argument cannot be InheritPriority");
658  return;
659  }
660 
661  if (!SetThreadPriority(d->handle, prio)) {
662  qErrnoWarning("QThread::setPriority: Failed to set thread priority");
663  }
664 }
665 
667 #endif // QT_NO_THREAD
double d
Definition: qnumeric_p.h:62
virtual void run()
The starting point for the thread.
Definition: qthread.cpp:628
static mach_timebase_info_data_t info
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
static void finish(void **)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void lock()
Locks the mutex.
Definition: qmutex.cpp:151
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
void remove(int i)
Removes the element at index position i.
Definition: qvector.h:374
#define ULONG_PTR
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
static void * start(void *arg)
void finished()
This signal is emitted when the thread has finished executing.
void unlock()
Unlocks this mutex locker.
Definition: qmutex.h:117
static void qt_free_tls()
Definition: qthread_win.cpp:87
#define _beginthreadex(a, b, c, d, e, f)
static QThread * theMainThread
QVector< void * > tls
Definition: qthread_p.h:268
bool isAdopted
Definition: qthread_p.h:269
static void clearCurrentThreadData()
void started()
This signal is emitted when the thread starts executing.
static DWORD qt_current_thread_data_tls_index
Definition: qthread_win.cpp:77
#define Q_DESTRUCTOR_FUNCTION(AFUNC)
Definition: qglobal.h:839
static QMutex qt_adopted_thread_watcher_mutex
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define WAIT_OBJECT_0
DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
This function loops and waits for native adopted threads to finish.
#define Q_D(Class)
Definition: qglobal.h:2482
static QObjectPrivate * get(QObject *o)
Definition: qobject_p.h:177
unsigned int id
Definition: qthread_p.h:175
void deref()
Definition: qthread.cpp:125
#define QT_ENSURE_STACK_ALIGNED_FOR_SSE
Definition: qglobal.h:1176
static void yieldCurrentThread()
Yields execution of the current thread to another runnable thread, if any.
void relock()
Relocks an unlocked mutex locker.
Definition: qmutex.h:125
static void msleep(unsigned long)
Forces the current thread to sleep for msecs milliseconds.
#define QT_RETHROW
Definition: qglobal.h:1539
static QThreadData * get2(QThread *thread)
Definition: qthread_p.h:219
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QThreadData(int initialRefCount=1)
Definition: qthread.cpp:79
static bool activateCallbacks(Callback, void **)
Definition: qglobal.cpp:3653
static bool init
bool terminatePending
Definition: qthread_p.h:183
#define emit
Definition: qobjectdefs.h:76
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
#define FALSE
Synonym for false.
Definition: qglobal.h:1019
static void sendPostedEvents()
void * HANDLE
Definition: qnamespace.h:1671
#define QT_CATCH(A)
Definition: qglobal.h:1537
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4049
static QVector< HANDLE > qt_adopted_thread_handles
bool quitNow
Definition: qthread_p.h:262
void unlock()
Unlocks the mutex.
Definition: qmutex.cpp:296
#define TLS_OUT_OF_INDEXES
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
QThreadData * data
Definition: qthread_p.h:185
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
void qt_create_tls()
Initializes the QThread system.
Definition: qthread_win.cpp:78
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
static DWORD dwThreadID
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:
QMutex mutex
Definition: qthread_p.h:145
const char * className() const
Returns the class name.
Definition: qobjectdefs.h:491
QString objectName() const
static QReadWriteLock lock
Definition: proxyconf.cpp:399
static QThreadData * current()
QThread::Priority priority
Definition: qthread_p.h:156
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.
Definition: qbytearray.h:421
const T * constData() const
Returns a const pointer to the data stored in the vector.
Definition: qvector.h:154
static void finish(void *)
static HANDLE qt_adopted_thread_wakeup
#define _endthreadex(a)
static void createEventDispatcher(QThreadData *data)
void prepend(const T &t)
Inserts value at the beginning of the vector.
Definition: qvector.h:378
QThread * thread
Definition: qthread_p.h:260
The QThread class provides a platform-independent way to manage threads.
Definition: qthread.h:59
Qt::HANDLE threadId
Definition: qthread_p.h:261
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
QAbstractEventDispatcher * eventDispatcher
Definition: qthread_p.h:264
#define QT_TRY
Definition: qglobal.h:1536
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.
bool terminationEnabled
Definition: qthread_p.h:183
QMutex * mutex() const
Returns a pointer to the mutex that was locked in the constructor.
Definition: qmutex.h:140
#define enabled
The QAbstractEventDispatcher class provides an interface to manage Qt&#39;s event queue.
virtual const QMetaObject * metaObject() const
Returns a pointer to the meta-object of this object.
int errno
HANDLE handle
Definition: qthread_p.h:174
static QVector< QThread * > qt_adopted_qthreads
void qErrnoWarning(const char *msg,...)
Definition: qglobal.cpp:2954
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.
Definition: qglobal.h:2452