From 586ba876034f46be1fe1c916f84f51392e60f3ef Mon Sep 17 00:00:00 2001 From: mread Date: Wed, 16 Feb 2011 14:17:36 +0000 Subject: Using a single monitor thread to monitor all adopted threads This reduces the number of extra threads required when native threads are adopted. In practice, the main thread is native and the montitor thread itself, so the monitor thread always ends up monitoring both. Task-number: QTBUG-13990 Reviewed-by: Shane Kearns --- src/corelib/thread/qthread_symbian.cpp | 162 ++++++++++++++++----------------- 1 file changed, 76 insertions(+), 86 deletions(-) diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp index 811d7da..bb1a4a7 100644 --- a/src/corelib/thread/qthread_symbian.cpp +++ b/src/corelib/thread/qthread_symbian.cpp @@ -118,146 +118,136 @@ QThreadData *QThreadData::current() return data; } -QMutex adoptedThreadMonitorMutex; -class QCAddAdoptedThread; -QCAddAdoptedThread* adoptedThreadAdder = 0; -QWaitCondition adoptedThreadAcceptWait; class QCAdoptedThreadMonitor : public CActive { public: - QCAdoptedThreadMonitor(QThreadData *data) - : CActive(EPriorityStandard), adoptedData(data) + QCAdoptedThreadMonitor(QThread *thread) + : CActive(EPriorityStandard), data(QThreadData::get2(thread)) { CActiveScheduler::Add(this); - adoptedData->symbian_thread_handle.Logon(iStatus); + data->symbian_thread_handle.Logon(iStatus); + SetActive(); + } + ~QCAdoptedThreadMonitor() + { + Cancel(); } - ~QCAdoptedThreadMonitor(); void DoCancel() { - adoptedData->symbian_thread_handle.LogonCancel(iStatus); + data->symbian_thread_handle.LogonCancel(iStatus); } void RunL() { - adoptedData->deref(); + data->deref(); delete this; } private: - QThreadData *adoptedData; + QThreadData* data; }; class QCAddAdoptedThread : public CActive { public: QCAddAdoptedThread() - : CActive(EPriorityStandard), count(0), dataToAdd(0) + : CActive(EPriorityStandard) { CActiveScheduler::Add(this); + } + void ConstructL() + { + User::LeaveIfError(monitorThread.Open(RThread().Id())); start(); } ~QCAddAdoptedThread() { Cancel(); + monitorThread.Close(); } - void RunL() - { - if (iStatus.Int() != KErrNone) - return; - - // Create an active object to monitor the thread - new (ELeave) QCAdoptedThreadMonitor(dataToAdd); - count++; - dataToAdd = 0; - start(); - - adoptedThreadAcceptWait.wakeAll(); - } - void add(QThreadData* data) + void DoCancel() { - dataToAdd = data; TRequestStatus *stat = &iStatus; - User::RequestComplete(stat, KErrNone); + User::RequestComplete(stat, KErrCancel); } void start() { iStatus = KRequestPending; SetActive(); } - void DoCancel() + void RunL() { - TRequestStatus *stat = &iStatus; - User::RequestComplete(stat, KErrCancel); + 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]); + threadsToAdd.pop_back(); + } + start(); } - void adoptedTheadClosed() + static void add(QThread* thread) { QMutexLocker adoptedThreadMonitorMutexlock(&adoptedThreadMonitorMutex); - count--; - if (!count) - { - adoptedThreadAdder = 0; - CActiveScheduler::Stop(); + 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(); + } + adoptedThreadAdder->threadsToAdd.push_back(thread); + if (adoptedThreadAdder->IsActive()) { + TRequestStatus *stat = &adoptedThreadAdder->iStatus; + adoptedThreadAdder->monitorThread.RequestComplete(stat, KErrNone); } } -private: - int count; - QThreadData* dataToAdd; -}; - -QCAdoptedThreadMonitor::~QCAdoptedThreadMonitor() -{ - Cancel(); - adoptedThreadAdder->adoptedTheadClosed(); -} - -void monitorThreadFuncL() -{ - CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); - CleanupStack::PushL(scheduler); - CActiveScheduler::Install(scheduler); - - adoptedThreadAdder = new(ELeave) QCAddAdoptedThread(); - RThread::Rendezvous(KErrNone); - CActiveScheduler::Start(); + static void monitorThreadFuncL() + { + CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); + CleanupStack::PushL(scheduler); + CActiveScheduler::Install(scheduler); - CleanupStack::PopAndDestroy(scheduler); -} + adoptedThreadAdder = new(ELeave) QCAddAdoptedThread(); + CleanupStack::PushL(adoptedThreadAdder); + adoptedThreadAdder->ConstructL(); -int monitorThreadFunc(void *) -{ - _LIT(KMonitorThreadName, "adoptedMonitorThread"); - RThread::RenameMe(KMonitorThreadName()); - CTrapCleanup* cleanup = CTrapCleanup::New(); - TRAPD(ret, monitorThreadFuncL()); - delete cleanup; - return ret; -} + RThread::Rendezvous(KErrNone); + CActiveScheduler::Start(); -void monitorThreadLifetime(QThreadData* data) - { - 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(); + CleanupStack::PopAndDestroy(adoptedThreadAdder); + adoptedThreadAdder = 0; + CleanupStack::PopAndDestroy(scheduler); } - adoptedThreadAdder->add(data); - QMutex waitLock; - waitLock.lock(); - adoptedThreadAcceptWait.wait(&waitLock); - waitLock.unlock(); + static int monitorThreadFunc(void *) + { + _LIT(KMonitorThreadName, "adoptedMonitorThread"); + RThread::RenameMe(KMonitorThreadName()); + CTrapCleanup* cleanup = CTrapCleanup::New(); + TRAPD(ret, monitorThreadFuncL()); + delete cleanup; + return ret; } +private: + QVector threadsToAdd; + RThread monitorThread; + static QMutex adoptedThreadMonitorMutex; + static QCAddAdoptedThread* adoptedThreadAdder; +}; + +QMutex QCAddAdoptedThread::adoptedThreadMonitorMutex; +QCAddAdoptedThread* QCAddAdoptedThread::adoptedThreadAdder = 0; + void QAdoptedThread::init() { Q_D(QThread); d->thread_id = RThread().Id(); // type operator to TUint init_symbian_thread_handle(d->data->symbian_thread_handle); - monitorThreadLifetime(d->data); + QCAddAdoptedThread::add(this); } /* -- cgit v0.12