diff options
author | mread <qt-info@nokia.com> | 2011-02-09 08:18:36 (GMT) |
---|---|---|
committer | mread <qt-info@nokia.com> | 2011-03-09 12:45:07 (GMT) |
commit | 834ad29849ebef99d7e5c516cde26d550abff7cd (patch) | |
tree | c3da2435c2bb23948eaff22c93f7f70fcd2c9aea /src/corelib/thread/qwaitcondition_symbian.cpp | |
parent | f351340d328a896829779794e8810f0d913161fb (diff) | |
download | Qt-834ad29849ebef99d7e5c516cde26d550abff7cd.zip Qt-834ad29849ebef99d7e5c516cde26d550abff7cd.tar.gz Qt-834ad29849ebef99d7e5c516cde26d550abff7cd.tar.bz2 |
Symbian native implementation of corelib/thread
QThread, QWaitCondition and QMutex have new Symbian native
implementations. These new implementations are split out into
new _symbian files.
Task-number: QTBUG-13990
Reviewed-by: Shane Kearns
Diffstat (limited to 'src/corelib/thread/qwaitcondition_symbian.cpp')
-rw-r--r-- | src/corelib/thread/qwaitcondition_symbian.cpp | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/src/corelib/thread/qwaitcondition_symbian.cpp b/src/corelib/thread/qwaitcondition_symbian.cpp new file mode 100644 index 0000000..83fa597 --- /dev/null +++ b/src/corelib/thread/qwaitcondition_symbian.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdefs.h" +#include "qwaitcondition.h" +#include "qmutex.h" +#include "qreadwritelock.h" +#include "qatomic.h" +#include "qstring.h" +#include "qelapsedtimer" +#include "qdebug.h" + +#include "qmutex_p.h" +#include "qreadwritelock_p.h" + +#include <errno.h> + +#ifndef QT_NO_THREAD + +QT_BEGIN_NAMESPACE + +static void report_error(int err, const char *where, const char *what) +{ + if (err != KErrNone) + qWarning("%s: %s failure: %d", where, what, err); +} + +class QWaitConditionPrivate { +public: + RMutex mutex; + RCondVar cond; + int waiters; + int wakeups; + int count; + + QWaitConditionPrivate() + : waiters(0), wakeups(0), count(0) + { + qt_symbian_throwIfError(mutex.CreateLocal()); + int err = cond.CreateLocal(); + if (err != KErrNone) { + mutex.Close(); + qt_symbian_throwIfError(err); + } + } + + ~QWaitConditionPrivate() + { + cond.Close(); + mutex.Close(); + } + + bool wait(unsigned long time) + { + TInt err = KErrNone; + if (time == ULONG_MAX) { + // untimed wait, loop because RCondVar::Wait may return before the condition is triggered + do { + // qDebug() << "about to wait forever"; + err = cond.Wait(mutex); + // qDebug() << "cond.Wait(mutex) returned"; + } while (err == KErrNone && wakeups == 0); + } else { + unsigned long maxWait = KMaxTInt / 1000; + QElapsedTimer waitTimer; + do { + waitTimer.start(); + unsigned long waitTime = qMin(maxWait, time); + // wait at least 1ms, as 0 means no wait + // qDebug() << "about to wait " << qMax(1ul, waitTime) * 1000; + err = cond.TimedWait(mutex, qMax(1ul, waitTime) * 1000); + // RCondVar::TimedWait may return before the condition is triggered, update the timeout with actual wait time + time -= qMin((unsigned long)waitTimer.elapsed(), waitTime); + // qDebug() << "err=" << err << " time=" << time << " wakeups=" << wakeups; + } while ((err == KErrNone && wakeups == 0) || (err == KErrTimedOut && time > 0)); + } + + Q_ASSERT_X(waiters > 0, "QWaitCondition::wait", "internal error (waiters)"); + --waiters; + if (err == KErrNone) { + Q_ASSERT_X(wakeups > 0, "QWaitCondition::wait", "internal error (wakeups)"); + --wakeups; + } + + mutex.Signal(); + + if (err && err != KErrTimedOut) + report_error(err, "QWaitCondition::wait()", "cv wait"); + return err == KErrNone; + } +}; + +QWaitCondition::QWaitCondition() +{ + d = new QWaitConditionPrivate; +} + +QWaitCondition::~QWaitCondition() +{ + delete d; +} + +void QWaitCondition::wakeOne() +{ + d->mutex.Wait(); + d->wakeups = qMin(d->wakeups + 1, d->waiters); + d->cond.Signal(); + d->count++; + d->mutex.Signal(); + if ((d->count%1000) == 999) + User::After(1); +} + +void QWaitCondition::wakeAll() +{ + d->mutex.Wait(); + d->wakeups = d->waiters; + d->cond.Broadcast(); + d->count++; + d->mutex.Signal(); + if ((d->count%1000) == 999) + User::After(1); +} + +bool QWaitCondition::wait(QMutex *mutex, unsigned long time) +{ + if (! mutex) + return false; + if (mutex->d->recursive) { + qWarning("QWaitCondition: cannot wait on recursive mutexes"); + return false; + } + + d->mutex.Wait(); + ++d->waiters; + mutex->unlock(); + + bool returnValue = d->wait(time); + + mutex->lock(); + + return returnValue; +} + +bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) +{ + if (!readWriteLock || readWriteLock->d->accessCount == 0) + return false; + if (readWriteLock->d->accessCount < -1) { + qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()"); + return false; + } + + d->mutex.Wait(); + ++d->waiters; + + int previousAccessCount = readWriteLock->d->accessCount; + readWriteLock->unlock(); + + bool returnValue = d->wait(time); + + if (previousAccessCount < 0) + readWriteLock->lockForWrite(); + else + readWriteLock->lockForRead(); + + return returnValue; +} + +QT_END_NAMESPACE + +#endif // QT_NO_THREAD |