Qt 4.8
qthread.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 #include "qthread.h"
43 #include "qthreadstorage.h"
44 #include "qmutex.h"
45 #include "qmutexpool_p.h"
46 #include "qreadwritelock.h"
48 
49 #include <qeventloop.h>
50 #include <qhash.h>
51 
52 #include "qthread_p.h"
53 #include "private/qcoreapplication_p.h"
54 
55 /*
56 #ifdef Q_OS_WIN32
57 # include "qt_windows.h"
58 #else
59 # include <unistd.h>
60 # include <netinet/in.h>
61 # include <sys/utsname.h>
62 # include <sys/socket.h>
63 */
64 /*
65 # elif defined(Q_OS_HPUX)
66 # include <sys/pstat.h>
67 # elif defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_MAC)
68 # include <sys/sysctl.h>
69 # endif
70 #endif
71 */
72 
74 
75 /*
76  QThreadData
77 */
78 
79 QThreadData::QThreadData(int initialRefCount)
80  : _ref(initialRefCount), thread(0), threadId(0),
81  quitNow(false), loopLevel(0), eventDispatcher(0), canWait(true), isAdopted(false)
82 {
83  // fprintf(stderr, "QThreadData %p created\n", this);
84 }
85 
87 {
88  Q_ASSERT(_ref == 0);
89 
90  // In the odd case that Qt is running on a secondary thread, the main
91  // thread instance will have been dereffed asunder because of the deref in
92  // QThreadData::current() and the deref in the pthread_destroy. To avoid
93  // crashing during QCoreApplicationData's global static cleanup we need to
94  // safeguard the main thread here.. This fix is a bit crude, but it solves
95  // the problem...
99  }
100 
101  QThread *t = thread;
102  thread = 0;
103  delete t;
104 
105  for (int i = 0; i < postEventList.size(); ++i) {
106  const QPostEvent &pe = postEventList.at(i);
107  if (pe.event) {
108  --pe.receiver->d_func()->postedEvents;
109  pe.event->posted = false;
110  delete pe.event;
111  }
112  }
113 
114  // fprintf(stderr, "QThreadData %p destroyed\n", this);
115 }
116 
118 {
119 #ifndef QT_NO_THREAD
120  (void) _ref.ref();
121  Q_ASSERT(_ref != 0);
122 #endif
123 }
124 
126 {
127 #ifndef QT_NO_THREAD
128  if (!_ref.deref())
129  delete this;
130 #endif
131 }
132 
133 /*
134  QAdoptedThread
135 */
136 
138  : QThread(*new QThreadPrivate(data))
139 {
140  // thread should be running and not finished for the lifetime
141  // of the application (even if QCoreApplication goes away)
142 #ifndef QT_NO_THREAD
143  d_func()->running = true;
144  d_func()->finished = false;
145  init();
146 #endif
147 
148  // fprintf(stderr, "new QAdoptedThread = %p\n", this);
149 }
150 
152 {
153  // fprintf(stderr, "~QAdoptedThread = %p\n", this);
154 }
155 
157 {
159  t->moveToThread(t.data());
160  return t.take();
161 }
162 
164 {
165  // this function should never be called
166  qFatal("QAdoptedThread::run(): Internal error, this implementation should never be called.");
167 }
168 #ifndef QT_NO_THREAD
169 /*
170  QThreadPrivate
171 */
172 
174  : QObjectPrivate(), running(false), finished(false), terminated(false),
175  isInFinish(false), exited(false), returnCode(-1),
177 {
178 #if defined (Q_OS_UNIX)
179  thread_id = 0;
180 #elif defined (Q_WS_WIN)
181  handle = 0;
182  id = 0;
183  waiters = 0;
184 #endif
185 #if defined (Q_WS_WIN) || defined (Q_OS_SYMBIAN)
186  terminationEnabled = true;
187  terminatePending = false;
188 #endif
189 
190  if (!data)
191  data = new QThreadData;
192 }
193 
195 {
196  data->deref();
197 }
198 
420 {
422  Q_ASSERT(data != 0);
423  return data->thread;
424 }
425 
434  : QObject(*(new QThreadPrivate), parent)
435 {
436  Q_D(QThread);
437  // fprintf(stderr, "QThreadData %p created for thread %p\n", d->data, this);
438  d->data->thread = this;
439 }
440 
444  : QObject(dd, parent)
445 {
446  Q_D(QThread);
447  // fprintf(stderr, "QThreadData %p taken from private data for thread %p\n", d->data, this);
448  d->data->thread = this;
449 }
450 
461 {
462  Q_D(QThread);
463  {
464  QMutexLocker locker(&d->mutex);
465  if (d->isInFinish) {
466  locker.unlock();
467  wait();
468  locker.relock();
469  }
470  if (d->running && !d->finished && !d->data->isAdopted)
471  qWarning("QThread: Destroyed while thread is still running");
472 
473  d->data->thread = 0;
474  }
475 }
476 
483 {
484  Q_D(const QThread);
485  QMutexLocker locker(&d->mutex);
486  return d->finished || d->isInFinish;
487 }
488 
494 bool QThread::isRunning() const
495 {
496  Q_D(const QThread);
497  QMutexLocker locker(&d->mutex);
498 #ifdef Q_OS_SYMBIAN
499  // app shutdown on Symbian can terminate threads and invalidate their stacks without notification,
500  // check the thread is still alive.
501  if (d->data->symbian_thread_handle.Handle() && d->data->symbian_thread_handle.ExitType() != EExitPending)
502  return false;
503 #endif
504  return d->running && !d->isInFinish;
505 }
506 
520 {
521  Q_D(QThread);
522  QMutexLocker locker(&d->mutex);
523  Q_ASSERT_X(!d->running, "QThread::setStackSize",
524  "cannot change stack size while the thread is running");
525  d->stackSize = stackSize;
526 }
527 
535 {
536  Q_D(const QThread);
537  QMutexLocker locker(&d->mutex);
538  return d->stackSize;
539 }
540 
552 {
553  Q_D(QThread);
554  QMutexLocker locker(&d->mutex);
555  d->data->quitNow = false;
556  if (d->exited) {
557  d->exited = false;
558  return d->returnCode;
559  }
560  locker.unlock();
561 
562  QEventLoop eventLoop;
563  int returnCode = eventLoop.exec();
564 
565  locker.relock();
566  d->exited = false;
567  d->returnCode = -1;
568  return returnCode;
569 }
570 
592 void QThread::exit(int returnCode)
593 {
594  Q_D(QThread);
595  QMutexLocker locker(&d->mutex);
596  d->exited = true;
597  d->returnCode = returnCode;
598  d->data->quitNow = true;
599  for (int i = 0; i < d->data->eventLoops.size(); ++i) {
600  QEventLoop *eventLoop = d->data->eventLoops.at(i);
601  eventLoop->exit(returnCode);
602  }
603 }
604 
615 { exit(); }
616 
629 {
630  (void) exec();
631 }
632 
639 #if defined (Q_OS_WIN)
640 void qt_create_tls();
641 #endif
642 
644 {
646  return;
648 
649 #if defined (Q_OS_WIN)
650  qt_create_tls();
651 #endif
652 }
653 
654 
662 {
664 }
665 
719 {
720  Q_D(const QThread);
721  QMutexLocker locker(&d->mutex);
722 
723  // mask off the high bits that are used for flags
724  return Priority(d->priority & 0xffff);
725 }
726 
839 #else // QT_NO_THREAD
840 
842  : QObject(*(new QThreadPrivate), (QObject*)0){
843  Q_D(QThread);
844  d->data->thread = this;
845 }
846 
848 {
849  return QThreadData::current()->thread;
850 }
851 
853 {
854  static QThreadData *data = 0; // reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
855  if (!data) {
857  newdata->thread = new QAdoptedThread(newdata.data());
858  data = newdata.take();
859  data->deref();
860  }
861  return data;
862 }
863 
867  : QObject(dd, parent)
868 {
869  Q_D(QThread);
870  // fprintf(stderr, "QThreadData %p taken from private data for thread %p\n", d->data, this);
871  d->data->thread = this;
872 }
873 
874 #endif // QT_NO_THREAD
875 
double d
Definition: qnumeric_p.h:62
virtual void run()
The starting point for the thread.
Definition: qthread.cpp:628
static void cleanup()
Cleans up the QThread system.
Definition: qthread.cpp:661
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
pthread_t thread_id
Definition: qthread_p.h:161
T * data() const
Returns the value of the pointer referenced by this object.
~QThread()
Destroys the QThread.
Definition: qthread.cpp:460
void setStackSize(uint stackSize)
Sets the maximum stack size for the thread to stackSize.
Definition: qthread.cpp:519
uint stackSize() const
Returns the maximum stack size for the thread (if set with setStackSize()); otherwise returns zero...
Definition: qthread.cpp:534
QThread(QObject *parent=0)
Constructs a new QThread to manage a new thread.
Definition: qthread.cpp:433
T * take()
Returns the value of the pointer referenced by this object.
void finished()
This signal is emitted when the thread has finished executing.
void unlock()
Unlocks this mutex locker.
Definition: qmutex.h:117
static QThread * theMainThread
bool ref()
Atomically increments the value of this QAtomicInt.
static void clearCurrentThreadData()
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define Q_D(Class)
Definition: qglobal.h:2482
Priority
This enum type indicates how the operating system should schedule newly created threads.
Definition: qthread.h:70
void quit()
Tells the thread&#39;s event loop to exit with return code 0 (success).
Definition: qthread.cpp:614
void deref()
Definition: qthread.cpp:125
QAdoptedThread(QThreadData *data=0)
Definition: qthread.cpp:137
Priority priority() const
Returns the priority for a running thread.
Definition: qthread.cpp:718
void relock()
Relocks an unlocked mutex locker.
Definition: qmutex.h:125
static QThread * currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
Definition: qthread.cpp:419
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QEventLoop class provides a means of entering and leaving an event loop.
Definition: qeventloop.h:55
QThreadData(int initialRefCount=1)
Definition: qthread.cpp:79
bool terminatePending
Definition: qthread_p.h:183
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
bool deref()
Atomically decrements the value of this QAtomicInt.
static QMutexPool * instance()
Returns the global QMutexPool instance.
Definition: qmutexpool.cpp:124
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
QPostEventList postEventList
Definition: qthread_p.h:266
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
Definition: qobject.cpp:1458
Q_CORE_EXPORT QMutexPool * qt_global_mutexpool
Definition: qmutexpool.cpp:51
ushort posted
Definition: qcoreevent.h:319
QThreadPrivate(QThreadData *d=0)
Definition: qthread.cpp:173
QThreadData * data
Definition: qthread_p.h:185
QEvent * event
Definition: qthread_p.h:78
Q_CORE_EXPORT void qFatal(const char *,...)
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
void exit(int returnCode=0)
Tells the event loop to exit with a return code.
Definition: qeventloop.cpp:288
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
void terminated()
This signal is emitted when the thread is terminated.
void ref()
Definition: qthread.cpp:117
QObject * receiver
Definition: qthread_p.h:77
Q_INVOKABLE QObject(QObject *parent=0)
Constructs an object with parent object parent.
Definition: qobject.cpp:753
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
bool wait(unsigned long time=ULONG_MAX)
Blocks the thread until either of these conditions is met:
~QThreadData()
Definition: qthread.cpp:86
int exec()
Enters the event loop and waits until exit() is called, returning the value that was passed to exit()...
Definition: qthread.cpp:551
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
static void initialize()
Definition: qthread.cpp:643
static QThreadData * current()
QObject * parent
Definition: qobject.h:92
static QThread * createThreadForAdoption()
Definition: qthread.cpp:156
bool isFinished() const
Returns true if the thread is finished; otherwise returns false.
Definition: qthread.cpp:482
QAtomicInt _ref
Definition: qthread_p.h:211
QThread * thread
Definition: qthread_p.h:260
The QThread class provides a platform-independent way to manage threads.
Definition: qthread.h:59
bool isRunning() const
Returns true if the thread is running; otherwise returns false.
Definition: qthread.cpp:494
bool terminationEnabled
Definition: qthread_p.h:183
int exec(ProcessEventsFlags flags=AllEvents)
Enters the main event loop and waits until exit() is called.
Definition: qeventloop.cpp:181
void exit(int retcode=0)
Tells the thread&#39;s event loop to exit with a return code.
Definition: qthread.cpp:592
HANDLE handle
Definition: qthread_p.h:174
void qt_create_tls()
Initializes the QThread system.
Definition: qthread_win.cpp:78
void run()
The starting point for the thread.
Definition: qthread.cpp:163