summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qwaitcondition_unix.cpp
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2015-11-06 09:37:23 +0100
committerOlivier Goffart (Woboq GmbH) <ogoffart@woboq.com>2016-03-11 13:32:13 +0000
commit343e5d066a6b5583688e16baec20f20e6d9a24e0 (patch)
tree41e1d382cd9e87ef2bfbe39e6e8bafcff1bbb0e1 /src/corelib/thread/qwaitcondition_unix.cpp
parent71548ba4a02e7d80a5ea407ff910b70ca21f9b5b (diff)
Optimized implementation of QReadWriteLock
QReadWriteLock is supposed to be a better alternative to QMutex when there are only a few writers but potentially lots of reads. However, in practice the previous implementation was much slower, unless you really do a lot of work with the lock for read and you have lots of contention. Indeed, the previous implementation was locking a QMutex both for lock, and unlock (making it already at least twice as slow as QMutex). This new implementation brings QReadWriteLock back to the same level as QMutex: - No memory allocations in the uncontended case (almost no overhead allowing to create many of them in classes) - Lock-free if there is no contention Should support up to 2^31 concurrent readers on 64 bit platforms, and 2^28 on 32 bit platforms Change-Id: Ifa2fc999075cbb971088f4ee8e6fde78ce262da3 Reviewed-by: Edward Welbourne <edward.welbourne@theqtcompany.com> Reviewed-by: Sean Harmer <sean.harmer@kdab.com> Reviewed-by: Robin Burchell <robin.burchell@viroteck.net>
Diffstat (limited to 'src/corelib/thread/qwaitcondition_unix.cpp')
-rw-r--r--src/corelib/thread/qwaitcondition_unix.cpp10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp
index 2a98fd2897..6adee5412e 100644
--- a/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/src/corelib/thread/qwaitcondition_unix.cpp
@@ -221,9 +221,12 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
{
- if (!readWriteLock || readWriteLock->d->accessCount == 0)
+ if (!readWriteLock)
return false;
- if (readWriteLock->d->accessCount < -1) {
+ auto previousState = readWriteLock->stateForWaitCondition();
+ if (previousState == QReadWriteLock::Unlocked)
+ return false;
+ if (previousState == QReadWriteLock::RecursivelyLocked) {
qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
return false;
}
@@ -231,12 +234,11 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
++d->waiters;
- int previousAccessCount = readWriteLock->d->accessCount;
readWriteLock->unlock();
bool returnValue = d->wait(time);
- if (previousAccessCount < 0)
+ if (previousState == QReadWriteLock::LockedForWrite)
readWriteLock->lockForWrite();
else
readWriteLock->lockForRead();