1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the core module of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
30
#include "qthreadstorage.h"
32
#include "qmutexpool_p.h"
33
#include "qreadwritelock.h"
35
#include <qeventloop.h>
38
#include "qthread_p.h"
45
QThreadData::QThreadData()
46
: id(-1), quitNow(false), allowDeferredDelete(false), eventDispatcher(0), tls(0)
49
QThreadData::~QThreadData()
51
for (int i = 0; i < postEventList.size(); ++i) {
52
const QPostEvent &pe = postEventList.at(i);
54
--pe.receiver->d_func()->postedEvents;
56
if (pe.event->type() == QEvent::ChildInserted)
57
--pe.receiver->d_func()->postedChildInsertedEvents;
59
pe.event->posted = false;
65
QThreadData *QThreadData::get(QThread *thread)
67
Q_ASSERT_X(thread != 0, "QThread", "internal error");
68
return &thread->d_func()->data;
77
QThreadPrivate::QThreadPrivate()
78
: QObjectPrivate(), running(false), finished(false), terminated(false),
81
#if defined (Q_OS_UNIX)
83
#elif defined (Q_WS_WIN)
87
terminationEnabled = true;
88
terminatePending = false;
91
static QBasicAtomic idCounter = Q_ATOMIC_INIT(1);
94
if (idCounter.testAndSet(data.id, data.id + 1))
99
struct QThreadIdHash {
101
QHash<int, QThread *> table;
104
Q_GLOBAL_STATIC(QThreadIdHash, threadIdHash)
108
QThread *QThreadPrivate::threadForId(int id)
110
QThreadIdHash *idHash = threadIdHash();
113
QReadLocker locker(&idHash->lock);
114
return idHash->table.value(id);
119
\brief The QThread class provides platform-independent threads.
125
A QThread represents a separate thread of control within the
126
program; it shares data with all the other threads within the
127
process but executes independently in the way that a separate
128
program does on a multitasking operating system. Instead of
129
starting in \c main(), QThreads begin executing in run().
130
To create your own threads, subclass QThread and reimplement
134
class MyThread : public QThread
143
// connect QTcpSocket's signals somewhere meaningful
145
socket.connectToHost(hostName, portNumber);
150
This will create a QTcpSocket in the thread and then execute the
151
thread's event loop. Use the start() method to begin execution.
152
Execution ends when you return from run(), just as an application
153
does when it leaves main(). QThread will notifiy you via a signal
154
when the thread is started(), finished(), and terminated(), or
155
you can use isFinished() and isRunning() to query the state of
156
the thread. Use wait() to block until the thread has finished
159
Each thread gets its own stack from the operating system. The
160
operating system also determines the default size of the stack.
161
You can use setStackSize() to set a custom stack size.
163
Each QThread can have its own event loop. You can start the event
164
loop by calling exec(); you can stop it by calling exit() or
165
quit(). Having an event loop in a thread makes it possible to
166
connect signals from other threads to slots in this threads,
167
using a mechanism called \l{Qt::QueuedConnection}{queued
168
connections}. It also makes it possible to use classes that
169
require the event loop, such as QTimer and QTcpSocket, in the
172
In extreme cases, you may want to forcibly terminate() an
173
executing thread. However, doing so is dangerous and discouraged.
174
Please read the documentation for terminate() and
175
setTerminationEnabled() for detailed information.
177
The static functions currentThreadId() and currentThread() return
178
identifiers for the currently executing thread. The former
179
returns a platform specific ID for the thread; the latter returns
182
QThread also provides platform independent sleep functions in
183
varying resolutions. Use sleep() for full second resolution,
184
msleep() for millisecond resolution, and usleep() for microsecond
187
\sa {threads.html}{Thread Support in Qt}, QThreadStorage, QMutex, QSemaphore, QWaitCondition
191
\fn void QThread::started()
193
This signal is emitted when the thread starts executing.
195
\sa finished(), terminated()
199
\fn void QThread::finished()
201
This signal is emitted when the thread has finished executing.
203
\sa started(), terminated()
207
\fn void QThread::terminated()
209
This signal is emitted when the thread is terminated.
211
\sa started(), finished()
215
\enum QThread::Priority
217
This enum type indicates how the operating system should schedule
218
newly created threads.
220
\value IdlePriority scheduled only when no other threads are
223
\value LowestPriority scheduled less often than LowPriority.
224
\value LowPriority scheduled less often than NormalPriority.
226
\value NormalPriority the default priority of the operating
229
\value HighPriority scheduled more often than NormalPriority.
230
\value HighestPriority scheduled more often than HighPriority.
232
\value TimeCriticalPriority scheduled as often as possible.
234
\value InheritPriority use the same priority as the creating
235
thread. This is the default.
239
Constructs a new thread with the given \a parent. The thread does
240
not begin executing until start() is called.
244
QThread::QThread(QObject *parent)
245
: QObject(*(new QThreadPrivate), parent)
248
QThreadIdHash *idHash = threadIdHash();
249
QWriteLocker locker(&idHash->lock);
250
idHash->table.insert(d->data.id, this);
256
Note that deleting a QThread object will not stop the execution
257
of the thread it represents. Deleting a running QThread (i.e.
258
isFinished() returns false) will probably result in a program
259
crash. You can wait() on a thread to make sure that it has
266
QMutexLocker locker(&d->mutex);
267
if (d->running && !d->finished)
268
qWarning("QThread object destroyed while thread is still running.");
271
QThreadIdHash *idHash = threadIdHash();
273
QWriteLocker locker(&idHash->lock);
274
idHash->table.remove(d->data.id);
279
Returns true is the thread is finished; otherwise returns false.
283
bool QThread::isFinished() const
286
QMutexLocker locker(&d->mutex);
291
Returns true if the thread is running; otherwise returns false.
295
bool QThread::isRunning() const
298
QMutexLocker locker(&d->mutex);
303
Sets the maximum stack size for the thread to \a stackSize. If \a
304
stackSize is greater than zero, the maximum stack size is set to
305
\a stackSize bytes, otherwise the maximum stack size is
306
automatically determined by the operating system.
308
\warning Most operating systems place minimum and maximum limits
309
on thread stack sizes. The thread will fail to start if the stack
310
size is outside these limits.
314
void QThread::setStackSize(uint stackSize)
317
QMutexLocker locker(&d->mutex);
318
Q_ASSERT_X(!d->running, "QThread::setStackSize",
319
"cannot change stack size while the thread is running");
320
d->stackSize = stackSize;
324
Returns the maximum stack size for the thread (if set with
325
setStackSize()); otherwise returns zero.
329
uint QThread::stackSize() const
332
QMutexLocker locker(&d->mutex);
337
Enters the event loop and waits until exit() is called or the main
338
widget is destroyed, and returns the value that was set to exit()
339
(which is 0 if exit() is called via quit()).
341
It is necessary to call this function to start event handling.
349
QEventLoop eventLoop;
351
int returnCode = eventLoop.exec();
356
Tells the thread's event loop to exit with a return code.
358
After calling this function, the thread leaves the event loop and
359
returns from the call to QEventLoop::exec(). The
360
QEventLoop::exec() function returns \a returnCode.
362
By convention, a \a returnCode of 0 means success, any non-zero value
365
Note that unlike the C library function of the same name, this
366
function \e does return to the caller -- it is event processing
369
This function does nothing if the thread does not have an event
372
\sa quit() QEventLoop
374
void QThread::exit(int returnCode)
377
QMutexLocker locker(&d->mutex);
378
d->data.quitNow = true;
379
for (int i = 0; i < d->data.eventLoops.size(); ++i) {
380
QEventLoop *eventLoop = d->data.eventLoops.at(i);
381
eventLoop->exit(returnCode);
386
Tells the thread's event loop to exit with return code 0 (success).
387
Equivalent to calling QThread::exit(0).
389
This function does nothing if the thread does not have an event
392
\sa exit() QEventLoop
398
\fn void QThread::run()
400
This method is pure virtual and must be implemented in derived
401
classes in order to do useful work. Returning from this method
402
will end the execution of the thread.
409
Initializes the QThread system.
411
void QThread::initialize()
413
if (qt_global_mutexpool)
415
qt_global_mutexpool = new QMutexPool(true);
417
#if defined (Q_OS_WIN)
418
extern void qt_create_tls();
425
Cleans up the QThread system.
427
void QThread::cleanup()
429
delete qt_global_mutexpool;
430
qt_global_mutexpool = 0;
434
\fn bool QThread::finished() const
436
Use isFinished() instead.
440
\fn bool QThread::running() const
442
Use isRunning() instead.