diff options
Diffstat (limited to 'src/corelib/concurrent/qtconcurrentthreadengine.cpp')
-rw-r--r-- | src/corelib/concurrent/qtconcurrentthreadengine.cpp | 98 |
1 files changed, 89 insertions, 9 deletions
diff --git a/src/corelib/concurrent/qtconcurrentthreadengine.cpp b/src/corelib/concurrent/qtconcurrentthreadengine.cpp index d6e6057..c6bde85 100644 --- a/src/corelib/concurrent/qtconcurrentthreadengine.cpp +++ b/src/corelib/concurrent/qtconcurrentthreadengine.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -47,6 +47,81 @@ QT_BEGIN_NAMESPACE namespace QtConcurrent { +ThreadEngineBarrier::ThreadEngineBarrier() +:count(0) { } + +void ThreadEngineBarrier::acquire() +{ + forever { + int localCount = int(count); + if (localCount < 0) { + if (count.testAndSetOrdered(localCount, localCount -1)) + return; + } else { + if (count.testAndSetOrdered(localCount, localCount + 1)) + return; + } + } +} + +int ThreadEngineBarrier::release() +{ + forever { + int localCount = int(count); + if (localCount == -1) { + if (count.testAndSetOrdered(-1, 0)) { + semaphore.release(); + return 0; + } + } else if (localCount < 0) { + if (count.testAndSetOrdered(localCount, localCount + 1)) + return qAbs(localCount + 1); + } else { + if (count.testAndSetOrdered(localCount, localCount - 1)) + return localCount - 1; + } + } +} + +// Wait until all threads have been released +void ThreadEngineBarrier::wait() +{ + forever { + int localCount = int(count); + if (localCount == 0) + return; + + Q_ASSERT(localCount > 0); // multiple waiters are not allowed. + if (count.testAndSetOrdered(localCount, -localCount)) { + semaphore.acquire(); + return; + } + } +} + +int ThreadEngineBarrier::currentCount() +{ + return int(count); +} + +// releases a thread, unless this is the last thread. +// returns true if the thread was released. +bool ThreadEngineBarrier::releaseUnlessLast() +{ + forever { + int localCount = int(count); + if (qAbs(localCount) == 1) { + return false; + } else if (localCount < 0) { + if (count.testAndSetOrdered(localCount, localCount + 1)) + return true; + } else { + if (count.testAndSetOrdered(localCount, localCount - 1)) + return true; + } + } +} + ThreadEngineBase::ThreadEngineBase() :futureInterface(0), threadPool(QThreadPool::globalInstance()) { @@ -66,7 +141,7 @@ void ThreadEngineBase::startSingleThreaded() void ThreadEngineBase::startBlocking() { start(); - semaphore.acquire(); + barrier.acquire(); startThreads(); bool throttled = false; @@ -88,10 +163,10 @@ void ThreadEngineBase::startBlocking() #endif if (throttled == false) { - semaphore.release(); + barrier.release(); } - semaphore.wait(); + barrier.wait(); finish(); exceptionStore.throwPossibleException(); } @@ -101,6 +176,11 @@ void ThreadEngineBase::startThread() startThreadInternal(); } +void ThreadEngineBase::acquireBarrierSemaphore() +{ + barrier.acquire(); +} + bool ThreadEngineBase::isCanceled() { if (futureInterface) @@ -138,9 +218,9 @@ bool ThreadEngineBase::startThreadInternal() if (this->isCanceled()) return false; - semaphore.acquire(); + barrier.acquire(); if (!threadPool->tryStart(this)) { - semaphore.release(); + barrier.release(); return false; } return true; @@ -155,7 +235,7 @@ void ThreadEngineBase::startThreads() void ThreadEngineBase::threadExit() { const bool asynchronous = futureInterface != 0; - const int lastThread = (semaphore.release() == 0); + const int lastThread = (barrier.release() == 0); if (lastThread && asynchronous) this->asynchronousFinish(); @@ -166,7 +246,7 @@ void ThreadEngineBase::threadExit() // this function returns one. bool ThreadEngineBase::threadThrottleExit() { - return semaphore.releaseUnlessLast(); + return barrier.releaseUnlessLast(); } void ThreadEngineBase::run() // implements QRunnable. |