summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2010-09-16 08:50:25 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2010-12-20 15:49:36 (GMT)
commitd9e35493d494df60d771a928a8d0dbde2b66906e (patch)
treee7a9922f2b2ce9deba4e4a8a08bda038a51b1310 /src/corelib
parent2d87a865b26250dcecbcf73178f8091e0724106d (diff)
downloadQt-d9e35493d494df60d771a928a8d0dbde2b66906e.zip
Qt-d9e35493d494df60d771a928a8d0dbde2b66906e.tar.gz
Qt-d9e35493d494df60d771a928a8d0dbde2b66906e.tar.bz2
Move contender count maintenance to QMutexPrivate
Make the cross-platform implementation of QMutex in qmutex.cpp only use testAndSetAcquire(0, 1) and testAndSetRelease(1, 0) like in the new inline functions in qmutex.h This will allow us to open up for more platform-specific optimizations to improve performance of contended QMutexes. Reviewed-by: joao
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/thread/qmutex.cpp43
-rw-r--r--src/corelib/thread/qmutex_unix.cpp5
-rw-r--r--src/corelib/thread/qmutex_win.cpp8
3 files changed, 21 insertions, 35 deletions
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index b85a22d..403468a 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -157,15 +157,12 @@ void QMutex::lock()
return;
}
- bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0;
+ bool isLocked = d->contenders.testAndSetAcquire(0, 1);
if (!isLocked) {
// didn't get the lock, wait for it
isLocked = d->wait();
Q_ASSERT_X(isLocked, "QMutex::lock",
"Internal error, infinite wait has timed out.");
-
- // don't need to wait for the lock anymore
- d->contenders.deref();
}
d->owner = self;
@@ -174,8 +171,7 @@ void QMutex::lock()
return;
}
-
- bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1);
+ bool isLocked = d->contenders.testAndSetAcquire(0, 1);
if (!isLocked) {
lockInternal();
}
@@ -211,7 +207,7 @@ bool QMutex::tryLock()
return true;
}
- bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1);
+ bool isLocked = d->contenders.testAndSetAcquire(0, 1);
if (!isLocked) {
// some other thread has the mutex locked, or we tried to
// recursively lock an non-recursive mutex
@@ -224,13 +220,7 @@ bool QMutex::tryLock()
return isLocked;
}
- bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1);
- if (!isLocked) {
- // some other thread has the mutex locked, or we tried to
- // recursively lock an non-recursive mutex
- return isLocked;
- }
- return isLocked;
+ return d->contenders.testAndSetAcquire(0, 1);
}
/*! \overload
@@ -269,13 +259,10 @@ bool QMutex::tryLock(int timeout)
return true;
}
- bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0;
+ bool isLocked = d->contenders.testAndSetAcquire(0, 1);
if (!isLocked) {
// didn't get the lock, wait for it
isLocked = d->wait(timeout);
-
- // don't need to wait for the lock anymore
- d->contenders.deref();
if (!isLocked)
return false;
}
@@ -286,17 +273,9 @@ bool QMutex::tryLock(int timeout)
return true;
}
- bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0;
- if (!isLocked) {
- // didn't get the lock, wait for it
- isLocked = d->wait(timeout);
-
- // don't need to wait for the lock anymore
- d->contenders.deref();
- if (!isLocked)
- return false;
- }
- return true;
+ return (d->contenders.testAndSetAcquire(0, 1)
+ // didn't get the lock, wait for it
+ || d->wait(timeout));
}
@@ -310,7 +289,6 @@ bool QMutex::tryLock(int timeout)
void QMutex::unlock()
{
QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d);
-
if (d->recursive) {
if (!--d->count) {
d->owner = 0;
@@ -460,16 +438,13 @@ void QMutex::lockInternal()
do {
if (spinCount++ > maximumSpinCount) {
// puts("spinning useless, sleeping");
- bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0;
+ bool isLocked = d->contenders.testAndSetAcquire(0, 1);
if (!isLocked) {
// didn't get the lock, wait for it
isLocked = d->wait();
Q_ASSERT_X(isLocked, "QMutex::lock",
"Internal error, infinite wait has timed out.");
-
- // don't need to wait for the lock anymore
- d->contenders.deref();
}
// decrease the lastSpinCount since we didn't actually get the lock by spinning
spinCount = -d->lastSpinCount / SpinCountPenalizationDivisor;
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index 7e7ef22..dcf8b9f 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -77,6 +77,10 @@ QMutexPrivate::~QMutexPrivate()
bool QMutexPrivate::wait(int timeout)
{
+ if (contenders.fetchAndAddAcquire(1) == 0) {
+ // lock acquired without waiting
+ return true;
+ }
report_error(pthread_mutex_lock(&mutex), "QMutex::lock", "mutex lock");
int errorCode = 0;
while (!wakeup) {
@@ -101,6 +105,7 @@ bool QMutexPrivate::wait(int timeout)
}
wakeup = false;
report_error(pthread_mutex_unlock(&mutex), "QMutex::lock", "mutex unlock");
+ contenders.deref();
return errorCode == 0;
}
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
index a810000..c278f04 100644
--- a/src/corelib/thread/qmutex_win.cpp
+++ b/src/corelib/thread/qmutex_win.cpp
@@ -60,7 +60,13 @@ QMutexPrivate::~QMutexPrivate()
bool QMutexPrivate::wait(int timeout)
{
- return WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0;
+ if (contenders.fetchAndAddAcquire(1) == 0) {
+ // lock acquired without waiting
+ return true;
+ }
+ bool returnValue = (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0);
+ contenders.deref();
+ return returnValue;
}
void QMutexPrivate::wakeUp()