diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/thread/qmutex_symbian.cpp | 101 | ||||
-rw-r--r-- | src/corelib/thread/qthread.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qthread_p.h | 13 | ||||
-rw-r--r-- | src/corelib/thread/qthread_symbian.cpp | 613 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition_symbian.cpp | 196 | ||||
-rw-r--r-- | src/corelib/thread/thread.pri | 6 |
6 files changed, 3 insertions, 928 deletions
diff --git a/src/corelib/thread/qmutex_symbian.cpp b/src/corelib/thread/qmutex_symbian.cpp deleted file mode 100644 index deac3f98ca..0000000000 --- a/src/corelib/thread/qmutex_symbian.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** 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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qplatformdefs.h" -#include "qmutex.h" - -#ifndef QT_NO_THREAD -#include "qatomic.h" -#include "qelapsedtimer.h" -#include "qthread.h" -#include "qmutex_p.h" - -QT_BEGIN_NAMESPACE - - -QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) - : QMutexData(mode), maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0) -{ - int r = lock.CreateLocal(0); - if (r != KErrNone) - qWarning("QMutex: failed to create lock, error %d", r); - qt_symbian_throwIfError(r); -} - -QMutexPrivate::~QMutexPrivate() -{ - lock.Close(); -} - -bool QMutexPrivate::wait(int timeout) -{ - if (contenders.fetchAndAddAcquire(1) == 0) { - // lock acquired without waiting - return true; - } - int r = KErrTimedOut; - if (timeout < 0) { - lock.Wait(); - r = KErrNone; - } else { - // Symbian lock waits are specified in microseconds. - // The wait is therefore chunked. - // KErrNone indicates success, KErrGeneral and KErrArgument are real fails, anything else is a timeout - do { - int waitTime = qMin(KMaxTInt / 1000, timeout); - timeout -= waitTime; - // Symbian undocumented feature - 0us means no timeout! Use a minimum of 1 - r = lock.Wait(qMax(1, waitTime * 1000)); - } while (r != KErrNone && r != KErrGeneral && r != KErrArgument && timeout > 0); - } - bool returnValue = (r == KErrNone); - contenders.deref(); - return returnValue; -} - -void QMutexPrivate::wakeUp() -{ - lock.Signal(); -} - -QT_END_NAMESPACE - -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 31332cd521..7a2e4b8f28 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -181,7 +181,7 @@ QThreadPrivate::QThreadPrivate(QThreadData *d) id = 0; waiters = 0; #endif -#if defined (Q_OS_WIN) || defined (Q_OS_SYMBIAN) +#if defined (Q_OS_WIN) terminationEnabled = true; terminatePending = false; #endif diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 461d93dd50..04f9bf23cf 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -62,9 +62,6 @@ #include "QtCore/qmap.h" #include "private/qobject_p.h" -#ifdef Q_OS_SYMBIAN -#include <e32base.h> -#endif QT_BEGIN_NAMESPACE @@ -162,11 +159,7 @@ public: QWaitCondition thread_done; static void *start(void *arg); -#if defined(Q_OS_SYMBIAN) - static void finish(void *arg, bool lockAnyway=true, bool closeNativeHandle=true); -#else static void finish(void *); -#endif #endif // Q_OS_UNIX @@ -179,7 +172,7 @@ public: static void finish(void *, bool lockAnyway=true); #endif // Q_OS_WIN32 -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined (Q_OS_SYMBIAN) +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) bool terminationEnabled, terminatePending; # endif QThreadData *data; @@ -232,10 +225,6 @@ public: bool canWait; QVector<void *> tls; bool isAdopted; - -# ifdef Q_OS_SYMBIAN - RThread symbian_thread_handle; -# endif }; // thread wrapper for the main() thread diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp deleted file mode 100644 index c515ae6d17..0000000000 --- a/src/corelib/thread/qthread_symbian.cpp +++ /dev/null @@ -1,613 +0,0 @@ -/**************************************************************************** -** -** 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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qthread.h" -#include "qplatformdefs.h" -#include <private/qcoreapplication_p.h> -#include <private/qeventdispatcher_symbian_p.h> -#include "qthreadstorage.h" -#include "qthread_p.h" -#include <private/qsystemerror_p.h> - -#include <sched.h> -#include <hal.h> -#include <hal_data.h> - -// You only find these enumerations on Symbian^3 onwards, so we need to provide our own -// to remain compatible with older releases. They won't be called by pre-Sym^3 SDKs. - -// HALData::ENumCpus -#define QT_HALData_ENumCpus 119 - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_THREAD - -enum { ThreadPriorityResetFlag = 0x80000000 }; - -// Utility functions for getting, setting and clearing thread specific data. -static QThreadData *get_thread_data() -{ - return reinterpret_cast<QThreadData *>(Dll::Tls()); -} - -static void set_thread_data(QThreadData *data) -{ - qt_symbian_throwIfError(Dll::SetTls(data)); -} - -static void clear_thread_data() -{ - Dll::FreeTls(); -} - - -static void init_symbian_thread_handle(RThread &thread) -{ - thread = RThread(); - TThreadId threadId = thread.Id(); - qt_symbian_throwIfError(thread.Open(threadId, EOwnerProcess)); -} - -QThreadData *QThreadData::current() -{ - QThreadData *data = get_thread_data(); - if (!data) { - void *a; - if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, &a)) { - QThread *adopted = static_cast<QThread*>(a); - Q_ASSERT(adopted); - data = QThreadData::get2(adopted); - set_thread_data(data); - adopted->d_func()->running = true; - adopted->d_func()->finished = false; - static_cast<QAdoptedThread *>(adopted)->init(); - } else { - data = new QThreadData; - QT_TRY { - set_thread_data(data); - data->thread = new QAdoptedThread(data); - } QT_CATCH(...) { - clear_thread_data(); - data->deref(); - data = 0; - QT_RETHROW; - } - data->deref(); - } - data->isAdopted = true; - data->threadId = QThread::currentThreadId(); - if (!QCoreApplicationPrivate::theMainThread) - QCoreApplicationPrivate::theMainThread = data->thread; - } - return data; -} - - -class QCAdoptedThreadMonitor : public CActive -{ -public: - QCAdoptedThreadMonitor(QThread *thread) - : CActive(EPriorityStandard), data(QThreadData::get2(thread)) - { - CActiveScheduler::Add(this); - data->symbian_thread_handle.Logon(iStatus); - SetActive(); - } - ~QCAdoptedThreadMonitor() - { - Cancel(); - } - void DoCancel() - { - data->symbian_thread_handle.LogonCancel(iStatus); - } - void RunL(); -private: - QThreadData* data; -}; - -class QCAddAdoptedThread : public CActive -{ -public: - QCAddAdoptedThread() - : CActive(EPriorityStandard) - { - CActiveScheduler::Add(this); - } - void ConstructL() - { - User::LeaveIfError(monitorThread.Open(RThread().Id())); - start(); - } - ~QCAddAdoptedThread() - { - Cancel(); - monitorThread.Close(); - } - void DoCancel() - { - User::RequestComplete(stat, KErrCancel); - } - void start() - { - iStatus = KRequestPending; - SetActive(); - stat = &iStatus; - } - void RunL() - { - if (iStatus.Int() != KErrNone) - return; - - QMutexLocker adoptedThreadMonitorMutexlock(&adoptedThreadMonitorMutex); - for (int i=threadsToAdd.size()-1; i>=0; i--) { - // Create an active object to monitor the thread - new (ELeave) QCAdoptedThreadMonitor(threadsToAdd[i]); - count++; - threadsToAdd.pop_back(); - } - start(); - } - static void add(QThread *thread) - { - QMutexLocker adoptedThreadMonitorMutexlock(&adoptedThreadMonitorMutex); - if (!adoptedThreadAdder) { - RThread monitorThread; - qt_symbian_throwIfError(monitorThread.Create(KNullDesC(), &monitorThreadFunc, 1024, &User::Allocator(), 0)); - TRequestStatus started; - monitorThread.Rendezvous(started); - monitorThread.Resume(); - User::WaitForRequest(started); - monitorThread.Close(); - } - if (RThread().Id() == adoptedThreadAdder->monitorThread.Id()) - return; - adoptedThreadAdder->threadsToAdd.push_back(thread); - if (adoptedThreadAdder->stat) { - adoptedThreadAdder->monitorThread.RequestComplete(adoptedThreadAdder->stat, KErrNone); - } - } - static void monitorThreadFuncL() - { - CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); - CleanupStack::PushL(scheduler); - CActiveScheduler::Install(scheduler); - - adoptedThreadAdder = new(ELeave) QCAddAdoptedThread(); - CleanupStack::PushL(adoptedThreadAdder); - adoptedThreadAdder->ConstructL(); - QCAddAdoptedThread *adder = adoptedThreadAdder; - - RThread::Rendezvous(KErrNone); - CActiveScheduler::Start(); - - CleanupStack::PopAndDestroy(adder); - CleanupStack::PopAndDestroy(scheduler); - } - static int monitorThreadFunc(void *) - { - _LIT(KMonitorThreadName, "adoptedMonitorThread"); - RThread::RenameMe(KMonitorThreadName()); - CTrapCleanup* cleanup = CTrapCleanup::New(); - TRAPD(ret, monitorThreadFuncL()); - delete cleanup; - return ret; - } - static void threadDied() - { - QMutexLocker adoptedThreadMonitorMutexlock(&adoptedThreadMonitorMutex); - if (adoptedThreadAdder) { - adoptedThreadAdder->count--; - if (adoptedThreadAdder->count <= 0 && adoptedThreadAdder->threadsToAdd.size() == 0) { - CActiveScheduler::Stop(); - adoptedThreadAdder = 0; - } - } - } - -private: - QVector<QThread*> threadsToAdd; - RThread monitorThread; - static QMutex adoptedThreadMonitorMutex; - static QCAddAdoptedThread *adoptedThreadAdder; - int count; - TRequestStatus *stat; -}; - -QMutex QCAddAdoptedThread::adoptedThreadMonitorMutex; -QCAddAdoptedThread* QCAddAdoptedThread::adoptedThreadAdder = 0; - -void QCAdoptedThreadMonitor::RunL() -{ - if (data->isAdopted) { - QThread *thread = data->thread; - Q_ASSERT(thread); - QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread)); - Q_ASSERT(!thread_p->finished); - thread_p->finish(thread); - } - data->deref(); - QCAddAdoptedThread::threadDied(); - delete this; -} - -void QAdoptedThread::init() -{ - Q_D(QThread); - d->thread_id = RThread().Id(); // type operator to TUint - init_symbian_thread_handle(d->data->symbian_thread_handle); - QCAddAdoptedThread::add(this); -} - -/* - QThreadPrivate -*/ - -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif - -typedef void*(*QtThreadCallback)(void*); - -#if defined(Q_C_CALLBACKS) -} -#endif - -#endif // QT_NO_THREAD - -void QThreadPrivate::createEventDispatcher(QThreadData *data) -{ - data->eventDispatcher = new QEventDispatcherSymbian; - data->eventDispatcher->startingUp(); -} - -#ifndef QT_NO_THREAD - -void *QThreadPrivate::start(void *arg) -{ - QThread *thr = reinterpret_cast<QThread *>(arg); - QThreadData *data = QThreadData::get2(thr); - - // do we need to reset the thread priority? - if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) { - thr->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag)); - } - - // On symbian, threads other than the main thread are non critical by default - // This means a worker thread can crash without crashing the application - to - // use this feature, we would need to use RThread::Logon in the main thread - // to catch abnormal thread exit and emit the finished signal. - // For the sake of cross platform consistency, we set the thread as process critical - // - advanced users who want the symbian behaviour can change the critical - // attribute of the thread again once the app gains control in run() - User::SetCritical(User::EProcessCritical); - - data->threadId = QThread::currentThreadId(); - set_thread_data(data); - - { - QMutexLocker locker(&thr->d_func()->mutex); - data->quitNow = thr->d_func()->exited; - } - - CTrapCleanup *cleanup = CTrapCleanup::New(); - - // ### TODO: allow the user to create a custom event dispatcher - createEventDispatcher(data); - - emit thr->started(); - thr->run(); - - QThreadPrivate::finish(arg); - - delete cleanup; - - return 0; -} - -void QThreadPrivate::finish(void *arg, bool lockAnyway, bool closeNativeHandle) -{ - QThread *thr = reinterpret_cast<QThread *>(arg); - QThreadPrivate *d = thr->d_func(); - - QMutexLocker locker(lockAnyway ? &d->mutex : 0); - - d->isInFinish = true; - d->priority = QThread::InheritPriority; - bool terminated = d->terminated; - void *data = &d->data->tls; - locker.unlock(); - if (terminated) - emit thr->terminated(); - emit thr->finished(); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - QThreadStorageData::finish((void **)data); - locker.relock(); - d->terminated = false; - - QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher; - if (eventDispatcher) { - d->data->eventDispatcher = 0; - locker.unlock(); - eventDispatcher->closingDown(); - delete eventDispatcher; - locker.relock(); - } - - d->thread_id = 0; - if (closeNativeHandle) - d->data->symbian_thread_handle.Close(); - d->running = false; - d->finished = true; - - d->isInFinish = false; - d->thread_done.wakeAll(); -} - - - - -/************************************************************************** - ** QThread - *************************************************************************/ - -Qt::HANDLE QThread::currentThreadId() -{ - return (Qt::HANDLE) (TUint) RThread().Id(); -} - -int QThread::idealThreadCount() -{ - int cores = 1; - - if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_3) { - TInt inumcpus; - TInt err; - err = HAL::Get((HALData::TAttribute)QT_HALData_ENumCpus, inumcpus); - if (err == KErrNone) { - cores = qMax(inumcpus, 1); - } - } - - return cores; -} - -void QThread::yieldCurrentThread() -{ - sched_yield(); -} - -/* \internal - helper function to do thread sleeps -*/ -static void thread_sleep(unsigned long remaining, unsigned long scale) -{ - // maximum Symbian wait is 2^31 microseconds - unsigned long maxWait = KMaxTInt / scale; - do { - unsigned long waitTime = qMin(maxWait, remaining); - remaining -= waitTime; - User::AfterHighRes(waitTime * scale); - } while (remaining); -} - -void QThread::sleep(unsigned long secs) -{ - thread_sleep(secs, 1000000ul); -} - -void QThread::msleep(unsigned long msecs) -{ - thread_sleep(msecs, 1000ul); -} - -void QThread::usleep(unsigned long usecs) -{ - thread_sleep(usecs, 1ul); -} - -TThreadPriority calculateSymbianPriority(QThread::Priority priority) - { - // Both Qt & Symbian use limited enums; this matches the mapping previously done through conversion to Posix granularity - TThreadPriority symPriority; - switch (priority) - { - case QThread::IdlePriority: - symPriority = EPriorityMuchLess; - break; - case QThread::LowestPriority: - case QThread::LowPriority: - symPriority = EPriorityLess; - break; - case QThread::NormalPriority: - symPriority = EPriorityNormal; - break; - case QThread::HighPriority: - symPriority = EPriorityMore; - break; - case QThread::HighestPriority: - case QThread::TimeCriticalPriority: - symPriority = EPriorityMuchMore; - break; - case QThread::InheritPriority: - default: - symPriority = RThread().Priority(); - break; - } - return symPriority; - } - -void QThread::start(Priority priority) -{ - Q_D(QThread); - QMutexLocker locker(&d->mutex); - - if (d->isInFinish) - d->thread_done.wait(locker.mutex()); - - if (d->running) - return; - - d->running = true; - d->finished = false; - d->terminated = false; - d->returnCode = 0; - d->exited = false; - - d->priority = priority; - - if (d->stackSize == 0) - // The default stack size on Symbian is very small, making even basic - // operations like file I/O fail, so we increase it by default. - d->stackSize = 0x14000; // Maximum stack size on Symbian. - - int code = d->data->symbian_thread_handle.Create(KNullDesC, (TThreadFunction) QThreadPrivate::start, d->stackSize, NULL, this); - if (code == KErrNone) { - d->thread_id = d->data->symbian_thread_handle.Id(); - TThreadPriority symPriority = calculateSymbianPriority(priority); - d->data->symbian_thread_handle.SetPriority(symPriority); - d->data->symbian_thread_handle.Resume(); - } else { - qWarning("QThread::start: Thread creation error: %s", qPrintable(QSystemError(code, QSystemError::NativeError).toString())); - - d->running = false; - d->finished = false; - d->thread_id = 0; - d->data->symbian_thread_handle.Close(); - } -} - -void QThread::terminate() -{ - Q_D(QThread); - QMutexLocker locker(&d->mutex); - - if (!d->thread_id) - return; - - if (!d->running) - return; - if (!d->terminationEnabled) { - d->terminatePending = true; - return; - } - - d->terminated = true; - // "false, false" meaning: - // 1. lockAnyway = false. Don't lock the mutex because it's already locked - // (see above). - // 2. closeNativeSymbianHandle = false. We don't want to close the thread handle, - // because we need it here to terminate the thread. - QThreadPrivate::finish(this, false, false); - d->data->symbian_thread_handle.Terminate(KErrNone); - d->data->symbian_thread_handle.Close(); -} - -bool QThread::wait(unsigned long time) -{ - Q_D(QThread); - QMutexLocker locker(&d->mutex); - - if (d->thread_id == (TUint) RThread().Id()) { - qWarning("QThread::wait: Thread tried to wait on itself"); - return false; - } - - if (d->finished || !d->running) - return true; - - while (d->running) { - // Check if thread still exists. Needed because kernel will kill it without notification - // before global statics are deleted at application exit. - if (d->data->symbian_thread_handle.Handle() - && d->data->symbian_thread_handle.ExitType() != EExitPending) { - // Cannot call finish here as wait is typically called from another thread. - // It won't be necessary anyway, as we should never get here under normal operations; - // all QThreads are EProcessCritical and therefore cannot normally exit - // undetected (i.e. panic) as long as all thread control is via QThread. - return true; - } - if (!d->thread_done.wait(locker.mutex(), time)) - return false; - } - return true; -} - -void QThread::setTerminationEnabled(bool enabled) -{ - QThread *thr = currentThread(); - Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()", - "Current thread was not started with QThread."); - QThreadPrivate *d = thr->d_func(); - QMutexLocker locker(&d->mutex); - d->terminationEnabled = enabled; - if (enabled && d->terminatePending) { - d->terminated = true; - // "false" meaning: - // - lockAnyway = false. Don't lock the mutex because it's already locked - // (see above). - QThreadPrivate::finish(thr, false); - locker.unlock(); // don't leave the mutex locked! - User::Exit(0); // may be some other cleanup required? what if AS or cleanup stack? - } -} - -void QThread::setPriority(Priority priority) -{ - Q_D(QThread); - QMutexLocker locker(&d->mutex); - if (!d->running) { - qWarning("QThread::setPriority: Cannot set priority, thread is not running"); - return; - } - - d->priority = priority; - - // copied from start() with a few modifications: - TThreadPriority symPriority = calculateSymbianPriority(priority); - d->data->symbian_thread_handle.SetPriority(symPriority); -} - -#endif // QT_NO_THREAD - -QT_END_NAMESPACE - diff --git a/src/corelib/thread/qwaitcondition_symbian.cpp b/src/corelib/thread/qwaitcondition_symbian.cpp deleted file mode 100644 index c6414e85c2..0000000000 --- a/src/corelib/thread/qwaitcondition_symbian.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/**************************************************************************** -** -** 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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qplatformdefs.h" -#include "qwaitcondition.h" -#include "qmutex.h" -#include "qreadwritelock.h" -#include "qatomic.h" -#include "qstring.h" -#include "qelapsedtimer.h" - -#include "qmutex_p.h" -#include "qreadwritelock_p.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; - - QWaitConditionPrivate() - : waiters(0), wakeups(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 { - err = cond.Wait(mutex); - } 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 - 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); - } 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->mutex.Signal(); -} - -void QWaitCondition::wakeAll() -{ - d->mutex.Wait(); - d->wakeups = d->waiters; - d->cond.Broadcast(); - d->mutex.Signal(); -} - -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 diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 309bf30d25..d63bb914e1 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -24,13 +24,9 @@ SOURCES += thread/qatomic.cpp \ thread/qthread.cpp \ thread/qthreadstorage.cpp -unix:!symbian:SOURCES += thread/qthread_unix.cpp \ +unix:SOURCES += thread/qthread_unix.cpp \ thread/qwaitcondition_unix.cpp -symbian:SOURCES += thread/qmutex_symbian.cpp \ - thread/qthread_symbian.cpp \ - thread/qwaitcondition_symbian.cpp - win32:SOURCES += thread/qmutex_win.cpp \ thread/qthread_win.cpp \ thread/qwaitcondition_win.cpp |