summaryrefslogtreecommitdiff
path: root/qmake/tools/qwaitcondition_unix.cpp
Side-by-side diff
Diffstat (limited to 'qmake/tools/qwaitcondition_unix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--qmake/tools/qwaitcondition_unix.cpp310
1 files changed, 310 insertions, 0 deletions
diff --git a/qmake/tools/qwaitcondition_unix.cpp b/qmake/tools/qwaitcondition_unix.cpp
new file mode 100644
index 0000000..99c1014
--- a/dev/null
+++ b/qmake/tools/qwaitcondition_unix.cpp
@@ -0,0 +1,310 @@
+/****************************************************************************
+** $Id$
+**
+** QWaitCondition class for Unix
+**
+** Created : 20010725
+**
+** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the tools module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#if defined(QT_THREAD_SUPPORT)
+
+#include "qplatformdefs.h"
+
+typedef pthread_mutex_t Q_MUTEX_T;
+
+#include "qwaitcondition.h"
+#include "qmutex.h"
+#include "qmutex_p.h"
+
+#include <errno.h>
+#include <string.h>
+
+
+struct QWaitConditionPrivate {
+ pthread_cond_t cond;
+};
+
+
+/*!
+ \class QWaitCondition qwaitcondition.h
+ \threadsafe
+ \brief The QWaitCondition class allows waiting/waking for conditions between threads.
+
+ \ingroup thread
+ \ingroup environment
+
+ QWaitConditions allow a thread to tell other threads that some
+ sort of condition has been met; one or many threads can block
+ waiting for a QWaitCondition to set a condition with wakeOne() or
+ wakeAll(). Use wakeOne() to wake one randomly selected event or
+ wakeAll() to wake them all. For example, say we have three tasks
+ that should be performed every time the user presses a key; each
+ task could be split into a thread, each of which would have a
+ run() body like this:
+
+ \code
+ QWaitCondition key_pressed;
+
+ for (;;) {
+ key_pressed.wait(); // This is a QWaitCondition global variable
+ // Key was pressed, do something interesting
+ do_something();
+ }
+ \endcode
+
+ A fourth thread would read key presses and wake the other three
+ threads up every time it receives one, like this:
+
+ \code
+ QWaitCondition key_pressed;
+
+ for (;;) {
+ getchar();
+ // Causes any thread in key_pressed.wait() to return from
+ // that method and continue processing
+ key_pressed.wakeAll();
+ }
+ \endcode
+
+ Note that the order the three threads are woken up in is
+ undefined, and that if some or all of the threads are still in
+ do_something() when the key is pressed, they won't be woken up
+ (since they're not waiting on the condition variable) and so the
+ task will not be performed for that key press. This can be
+ avoided by, for example, doing something like this:
+
+ \code
+ QMutex mymutex;
+ QWaitCondition key_pressed;
+ int mycount=0;
+
+ // Worker thread code
+ for (;;) {
+ key_pressed.wait(); // This is a QWaitCondition global variable
+ mymutex.lock();
+ mycount++;
+ mymutex.unlock();
+ do_something();
+ mymutex.lock();
+ mycount--;
+ mymutex.unlock();
+ }
+
+ // Key reading thread code
+ for (;;) {
+ getchar();
+ mymutex.lock();
+ // Sleep until there are no busy worker threads
+ while( count > 0 ) {
+ mymutex.unlock();
+ sleep( 1 );
+ mymutex.lock();
+ }
+ mymutex.unlock();
+ key_pressed.wakeAll();
+ }
+ \endcode
+
+ The mutexes are necessary because the results of two threads
+ attempting to change the value of the same variable simultaneously
+ are unpredictable.
+*/
+
+/*!
+ Constructs a new event signalling, i.e. wait condition, object.
+*/
+QWaitCondition::QWaitCondition()
+{
+ d = new QWaitConditionPrivate;
+
+ int ret = pthread_cond_init(&d->cond, NULL);
+
+#ifdef QT_CHECK_RANGE
+ if (ret)
+ qWarning( "Wait condition init failure: %s", strerror( ret ) );
+#endif
+}
+
+
+/*!
+ Deletes the event signalling, i.e. wait condition, object.
+*/
+QWaitCondition::~QWaitCondition()
+{
+ int ret = pthread_cond_destroy(&d->cond);
+
+ if (ret) {
+#ifdef QT_CHECK_RANGE
+ qWarning( "Wait condition destroy failure: %s", strerror( ret ) );
+#endif
+
+ // seems we have threads waiting on us, lets wake them up
+ pthread_cond_broadcast(&d->cond);
+ }
+
+ delete d;
+}
+
+/*!
+ This wakes one thread waiting on the QWaitCondition. The thread
+ that is woken up depends on the operating system's scheduling
+ policies, and cannot be controlled or predicted.
+
+ \sa wakeAll()
+*/
+void QWaitCondition::wakeOne()
+{
+ int ret = pthread_cond_signal(&d->cond);
+
+#ifdef QT_CHECK_RANGE
+ if (ret)
+ qWarning("Wait condition wakeOne failure: %s", strerror(ret));
+#endif
+}
+
+/*!
+ This wakes all threads waiting on the QWaitCondition. The order in
+ which the threads are woken up depends on the operating system's
+ scheduling policies, and cannot be controlled or predicted.
+
+ \sa wakeOne()
+*/
+void QWaitCondition::wakeAll()
+{
+ int ret = pthread_cond_broadcast(&d->cond);
+
+#ifdef QT_CHECK_RANGE
+ if (ret)
+ qWarning("Wait condition wakeAll failure: %s", strerror(ret));
+#endif
+}
+
+/*!
+ Wait on the thread event object. The thread calling this will
+ block until either of these conditions is met:
+ \list
+ \i Another thread signals it using wakeOne() or wakeAll(). This
+ function will return TRUE in this case.
+ \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the
+ default), then the wait will never timeout (the event must be
+ signalled). This function will return FALSE if the wait timed
+ out.
+ \endlist
+
+ \sa wakeOne(), wakeAll()
+*/
+bool QWaitCondition::wait(unsigned long time)
+{
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+ int ret;
+ if (time != ULONG_MAX) {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ timespec ti;
+ ti.tv_nsec = (tv.tv_usec * 1000) + (time % 1000) * 1000;
+ ti.tv_sec = tv.tv_sec + (time / 1000) + ( ti.tv_nsec / 1000000000 );
+ ti.tv_nsec %= 1000000000;
+
+ ret = pthread_cond_timedwait(&d->cond, &mutex, &ti);
+ } else
+ ret = pthread_cond_wait(&d->cond, &mutex);
+
+#ifdef QT_CHECK_RANGE
+ if (ret && ret != ETIMEDOUT)
+ qWarning("Wait condition wait failure: %s",strerror(ret));
+#endif
+
+ return (ret == 0);
+}
+
+/*!
+ \overload
+
+ Release the locked \a mutex and wait on the thread event object.
+ The \a mutex must be initially locked by the calling thread. If \a
+ mutex is not in a locked state, this function returns immediately.
+ If \a mutex is a recursive mutex, this function returns
+ immediately. The \a mutex will be unlocked, and the calling thread
+ will block until either of these conditions is met:
+ \list
+ \i Another thread signals it using wakeOne() or wakeAll(). This
+ function will return TRUE in this case.
+ \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the
+ default), then the wait will never timeout (the event must be
+ signalled). This function will return FALSE if the wait timed
+ out.
+ \endlist
+
+ The mutex will be returned to the same locked state. This function
+ is provided to allow the atomic transition from the locked state
+ to the wait state.
+
+ \sa wakeOne(), wakeAll()
+*/
+bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
+{
+ if (! mutex)
+ return FALSE;
+
+ if (mutex->d->type() == Q_MUTEX_RECURSIVE) {
+#ifdef QT_CHECK_RANGE
+ qWarning("Wait condition warning: using recursive mutexes with\n"
+ " wait conditions is undefined!");
+#endif
+ return FALSE;
+ }
+
+ int ret;
+ if (time != ULONG_MAX) {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ timespec ti;
+ ti.tv_nsec = (tv.tv_usec * 1000) + (time % 1000) * 1000;
+ ti.tv_sec = tv.tv_sec + (time / 1000) + ( ti.tv_nsec / 1000000000 );
+ ti.tv_nsec %= 1000000000;
+
+ ret = pthread_cond_timedwait(&d->cond, &mutex->d->handle, &ti);
+ } else
+ ret = pthread_cond_wait(&d->cond, &mutex->d->handle);
+
+#ifdef QT_CHECK_RANGE
+ if (ret && ret != ETIMEDOUT)
+ qWarning("Wait condition wait failure: %s",strerror(ret));
+#endif
+
+ return (ret == 0);
+}
+
+#endif // QT_THREAD_SUPPORT