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
****************************************************************************/
31
#include "qplatformdefs.h"
33
#include <private/qeventdispatcher_unix_p.h>
34
#include "qthreadstorage.h"
36
#include "qthread_p.h"
47
#if defined(Q_C_CALLBACKS)
51
typedef void*(*QtThreadCallback)(void*);
53
#if defined(Q_C_CALLBACKS)
57
static pthread_once_t current_thread_key_once = PTHREAD_ONCE_INIT;
58
static pthread_key_t current_thread_key;
59
static void create_current_thread_key()
60
{ pthread_key_create(¤t_thread_key, NULL); }
62
void QThreadPrivate::setCurrentThread(QThread *thread)
64
pthread_once(¤t_thread_key_once, create_current_thread_key);
65
pthread_setspecific(current_thread_key, thread);
68
void *QThreadPrivate::start(void *arg)
70
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
72
QThread *thr = reinterpret_cast<QThread *>(arg);
73
setCurrentThread(thr);
75
pthread_cleanup_push(QThreadPrivate::finish, arg);
77
QThreadData *data = QThreadData::get(thr);
78
data->quitNow = false;
79
// ### TODO: allow the user to create a custom event dispatcher
80
data->eventDispatcher = new QEventDispatcherUNIX;
81
data->eventDispatcher->startingUp();
84
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
88
pthread_cleanup_pop(1);
92
void QThreadPrivate::finish(void *arg)
94
QThread *thr = reinterpret_cast<QThread *>(arg);
95
QThreadPrivate *d = thr->d_func();
96
QThreadData *data = &d->data;
97
QMutexLocker locker(&d->mutex);
102
emit thr->terminated();
103
d->terminated = false;
104
emit thr->finished();
106
data->eventDispatcher->closingDown();
107
QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher;
108
data->eventDispatcher = 0;
109
delete eventDispatcher;
111
QThreadStorageData::finish(data->tls);
115
d->thread_done.wakeAll();
121
/**************************************************************************
123
*************************************************************************/
126
Returns the thread handle of the currently executing thread.
128
\warning The handle returned by this function is used for internal
129
purposes and should not be used in any application code. On
130
Windows, the returned value is a pseudo-handle for the current
131
thread that cannot be used for numerical comparison.
133
Qt::HANDLE QThread::currentThreadId()
135
// requires a C cast here otherwise we run into trouble on AIX
136
return (Qt::HANDLE)pthread_self();
140
Returns a pointer to the currently executing QThread. If the
141
current thread was not started using the QThread API (e.g., the
142
GUI thread), this function returns zero.
144
QThread *QThread::currentThread()
146
pthread_once(¤t_thread_key_once, create_current_thread_key);
147
return reinterpret_cast<QThread *>(pthread_getspecific(current_thread_key));
151
helper function to do thread sleeps, since usleep()/nanosleep()
152
aren't reliable enough (in terms of behavior and availability)
154
static void thread_sleep(struct timespec *ti)
159
pthread_mutex_init(&mtx, 0);
160
pthread_cond_init(&cnd, 0);
162
pthread_mutex_lock(&mtx);
163
(void) pthread_cond_timedwait(&cnd, &mtx, ti);
164
pthread_mutex_unlock(&mtx);
166
pthread_cond_destroy(&cnd);
167
pthread_mutex_destroy(&mtx);
171
Forces the current thread to sleep for \a secs seconds.
173
\sa msleep(), usleep()
175
void QThread::sleep(unsigned long secs)
178
gettimeofday(&tv, 0);
180
ti.tv_sec = tv.tv_sec + secs;
181
ti.tv_nsec = (tv.tv_usec * 1000);
186
Causes the current thread to sleep for \a msecs milliseconds.
188
\sa sleep(), usleep()
190
void QThread::msleep(unsigned long msecs)
193
gettimeofday(&tv, 0);
196
ti.tv_nsec = (tv.tv_usec + (msecs % 1000) * 1000) * 1000;
197
ti.tv_sec = tv.tv_sec + (msecs / 1000) + (ti.tv_nsec / 1000000000);
198
ti.tv_nsec %= 1000000000;
203
Causes the current thread to sleep for \a usecs microseconds.
205
\sa sleep(), msleep()
207
void QThread::usleep(unsigned long usecs)
210
gettimeofday(&tv, 0);
213
ti.tv_nsec = (tv.tv_usec + (usecs % 1000000)) * 1000;
214
ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (ti.tv_nsec / 1000000000);
215
ti.tv_nsec %= 1000000000;
220
Begins execution of the thread by calling run(), which should be
221
reimplemented in a QThread subclass to contain your code. The
222
operating system will schedule the thread according to the \a
223
priority parameter. If the thread is already running, this
224
function does nothing.
226
\sa run(), terminate()
228
void QThread::start(Priority priority)
231
QMutexLocker locker(&d->mutex);
237
d->terminated = false;
240
pthread_attr_init(&attr);
241
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
243
#if !defined(Q_OS_OPENBSD) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0)
245
case InheritPriority:
247
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
254
if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) {
255
// failed to get the scheduling policy, don't bother
256
// setting the priority
257
qWarning("QThread: cannot determine default scheduler policy");
261
int prio_min = sched_get_priority_min(sched_policy);
262
int prio_max = sched_get_priority_max(sched_policy);
263
if (prio_min == -1 || prio_max == -1) {
264
// failed to get the scheduling parameters, don't
265
// bother setting the priority
266
qWarning("QThread: cannot determine scheduler priority range");
276
case HighestPriority:
281
// crudely scale our priority enum values to the prio_min/prio_max
282
prio = (((prio_max - prio_min) / TimeCriticalPriority) * priority) + prio_min;
283
prio = qMax(prio_min, qMin(prio_max, prio));
288
sp.sched_priority = prio;
290
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
291
pthread_attr_setschedparam(&attr, &sp);
297
#endif // _POSIX_THREAD_PRIORITY_SCHEDULING
299
if (d->stackSize > 0) {
300
#if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0 > 0)
301
int code = pthread_attr_setstacksize(&attr, d->stackSize);
303
int code = ENOSYS; // stack size not supported, automatically fail
304
#endif // _POSIX_THREAD_ATTR_STACKSIZE
307
qWarning("QThread::start: thread stack size error: %s", strerror(code)) ;
309
// we failed to set the stacksize, and as the documentation states,
310
// the thread will fail to run...
318
pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
320
// caller does not have permission to set the scheduling
322
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
324
pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
327
pthread_attr_destroy(&attr);
330
qWarning("QThread::start: thread creation error: %s", strerror(code));
339
Terminates the execution of the thread. The thread may or may not
340
be terminated immediately, depending on the operating systems
341
scheduling policies. Use QThread::wait() after terminate() for
342
synchronous termination.
344
When the thread is terminated, all threads waiting for the thread
345
to finish will be woken up.
347
\warning This function is dangerous and its use is discouraged.
348
The thread can be terminate at any point in its code path.
349
Threads can be terminated while modifying data. There is no
350
chance for the thread to cleanup after itself, unlock any held
351
mutexes, etc. In short, use this function only if absolutely
354
Termination can be explicitly enabled or disabled by calling
355
QThread::setTerminationEnabled(). Calling this function while
356
termination is disabled results in the termination being
357
deferred, until termination is re-enabled. See the documentation
358
of QThread::setTerminationEnabled() for more information.
360
\sa setTerminationEnabled()
362
void QThread::terminate()
365
QMutexLocker locker(&d->mutex);
370
int code = pthread_cancel(d->thread_id);
372
qWarning("QThread::start: thread termination error: %s", strerror(code));
374
d->terminated = true;
379
Blocks the thread until either of these conditions is met:
382
\o The thread associated with this QThread object has finished
383
execution (i.e. when it returns from \l{run()}). This function
384
will return true if the thread has finished. It also returns
385
true if the thread has not been started yet.
386
\o \a time milliseconds has elapsed. If \a time is ULONG_MAX (the
387
default), then the wait will never timeout (the thread must
388
return from \l{run()}). This function will return false if the
392
This provides similar functionality to the POSIX \c
393
pthread_join() function.
395
\sa sleep(), terminate()
397
bool QThread::wait(unsigned long time)
400
QMutexLocker locker(&d->mutex);
402
if (d->thread_id == pthread_self()) {
403
qWarning("QThread::wait: thread tried to wait on itself");
407
if (d->finished || !d->running)
411
if (!d->thread_done.wait(locker.mutex(), time))
418
Enables or disables termination of the current thread based on the
419
\a enabled parameter. The thread must have been started by
422
When \a enabled is false, termination is disabled. Future calls
423
to QThread::terminate() will return immediately without effect.
424
Instead, the termination is deferred until termination is enabled.
426
When \a enabled is true, termination is enabled. Future calls to
427
QThread::terminate() will terminate the thread normally. If
428
termination has been deferred (i.e. QThread::terminate() was
429
called with termination disabled), this function will terminate
430
the calling thread \e immediately. Note that this function will
431
not return in this case.
435
void QThread::setTerminationEnabled(bool enabled)
437
Q_ASSERT_X(currentThread() != 0, "QThread::setTerminationEnabled()",
438
"Current thread was not started with QThread.");
439
pthread_setcancelstate(enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, NULL);
441
pthread_testcancel();