Make QBasicMutex be exclusively non-recursive
authorThiago Macieira <thiago.macieira@intel.com>
Sat, 11 Aug 2012 14:45:14 +0000 (16:45 +0200)
committerQt by Nokia <qt-info@nokia.com>
Fri, 14 Sep 2012 01:45:50 +0000 (03:45 +0200)
Dispatch to the recursive mutex functions from QMutex::lock, tryLock
and unlock.

This has the benefit that those using QBasicMutex will not go through
the testing for recursive mutexes. It simplifies a little the code for
those users.

For the users of QMutex, the code required to perform a lock does not
appear to change.

Change-Id: I0ca9965e012b283c30f1fab8e9f6d9b3288c2247
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
src/corelib/thread/qmutex.cpp
src/corelib/thread/qmutex.h
src/corelib/thread/qmutex_linux.cpp
src/corelib/thread/qmutex_p.h

index fa4fddc..2906a5a 100644 (file)
@@ -1,6 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Intel Corporation
 ** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtCore module of the Qt Toolkit.
 
 QT_BEGIN_NAMESPACE
 
+static inline bool isRecursive(QMutexData *d)
+{
+    register quintptr u = quintptr(d);
+    if (Q_LIKELY(u <= 0x3))
+        return false;
+#ifdef QT_LINUX_FUTEX
+    Q_ASSERT(d->recursive);
+    return true;
+#else
+    return d->recursive;
+#endif
+}
+
 /*
     \class QBasicMutex
     \inmodule QtCore
@@ -180,7 +194,13 @@ QMutex::~QMutex()
 */
 void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT
 {
-    QBasicMutex::lock();
+    if (fastTryLock())
+        return;
+    QMutexData *current = d_ptr.loadAcquire();
+    if (QT_PREPEND_NAMESPACE(isRecursive)(current))
+        static_cast<QRecursiveMutexPrivate *>(current)->lock(-1);
+    else
+        lockInternal();
 }
 
 /*! \fn bool QMutex::tryLock(int timeout)
@@ -208,7 +228,13 @@ void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT
 */
 bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
 {
-    return QBasicMutex::tryLock(timeout);
+    if (fastTryLock())
+        return true;
+    QMutexData *current = d_ptr.loadAcquire();
+    if (QT_PREPEND_NAMESPACE(isRecursive)(current))
+        return static_cast<QRecursiveMutexPrivate *>(current)->lock(timeout);
+    else
+        return lockInternal(timeout);
 }
 
 /*! \fn void QMutex::unlock()
@@ -220,7 +246,13 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
 */
 void QMutex::unlock() Q_DECL_NOTHROW
 {
-    QBasicMutex::unlock();
+    if (fastTryUnlock())
+        return;
+    QMutexData *current = d_ptr.loadAcquire();
+    if (QT_PREPEND_NAMESPACE(isRecursive)(current))
+        static_cast<QRecursiveMutexPrivate *>(current)->unlock();
+    else
+        unlockInternal();
 }
 
 /*!
@@ -230,16 +262,9 @@ void QMutex::unlock() Q_DECL_NOTHROW
     Returns true if the mutex is recursive
 
 */
-bool QBasicMutex::isRecursive() {
-    QMutexData *d = d_ptr.load();
-    if (quintptr(d) <= 0x3)
-        return false;
-#ifdef QT_LINUX_FUTEX
-    Q_ASSERT(d->recursive);
-    return true;
-#else
-    return d->recursive;
-#endif
+bool QBasicMutex::isRecursive()
+{
+    return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
 }
 
 
@@ -338,8 +363,7 @@ bool QBasicMutex::isRecursive() {
  */
 bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
 {
-    if (isRecursive())
-        return static_cast<QRecursiveMutexPrivate *>(d_ptr.load())->lock(timeout);
+    Q_ASSERT(!isRecursive());
 
     while (!fastTryLock()) {
         QMutexData *copy = d_ptr.loadAcquire();
@@ -435,11 +459,7 @@ void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
     QMutexData *copy = d_ptr.loadAcquire();
     Q_ASSERT(copy); //we must be locked
     Q_ASSERT(copy != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
-
-    if (copy->recursive) {
-        static_cast<QRecursiveMutexPrivate *>(copy)->unlock();
-        return;
-    }
+    Q_ASSERT(!isRecursive());
 
     QMutexPrivate *d = reinterpret_cast<QMutexPrivate *>(copy);
 
index 5d4d696..dd718c4 100644 (file)
@@ -71,7 +71,7 @@ public:
 
     inline void unlock() Q_DECL_NOTHROW {
         Q_ASSERT(d_ptr.load()); //mutex must be locked
-        if (!d_ptr.testAndSetRelease(dummyLocked(), 0))
+        if (!fastTryUnlock())
             unlockInternal();
     }
 
@@ -85,6 +85,10 @@ private:
     inline bool fastTryLock() Q_DECL_NOTHROW {
         return d_ptr.testAndSetAcquire(0, dummyLocked());
     }
+    inline bool fastTryUnlock() Q_DECL_NOTHROW {
+        return d_ptr.testAndSetRelease(dummyLocked(), 0);
+    }
+
     bool lockInternal(int timeout = -1) QT_MUTEX_LOCK_NOEXCEPT;
     void unlockInternal() Q_DECL_NOTHROW;
 
index 09db046..a17e9d0 100644 (file)
@@ -116,13 +116,9 @@ static inline QMutexData *dummyFutexValue()
 
 bool QBasicMutex::lockInternal(int timeout) Q_DECL_NOTHROW
 {
-    // we're here because fastTryLock() has just failed
-    QMutexData *d = d_ptr.load();
-    if (quintptr(d) > 0x3) { //d == dummyLocked() || d == dummyFutexValue()
-        Q_ASSERT(d->recursive);
-        return static_cast<QRecursiveMutexPrivate *>(d)->lock(timeout);
-    }
+    Q_ASSERT(!isRecursive());
 
+    // we're here because fastTryLock() has just failed
     if (timeout == 0)
         return false;
 
@@ -167,15 +163,11 @@ void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
     QMutexData *d = d_ptr.load();
     Q_ASSERT(d); //we must be locked
     Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
+    Q_UNUSED(d);
+    Q_ASSERT(!isRecursive());
 
-    if (d == dummyFutexValue()) {
-        d_ptr.fetchAndStoreRelease(0);
-        _q_futex(&d_ptr, FUTEX_WAKE, 1, 0);
-        return;
-    }
-
-    Q_ASSERT(d->recursive);
-    static_cast<QRecursiveMutexPrivate *>(d)->unlock();
+    d_ptr.fetchAndStoreRelease(0);
+    _q_futex(&d_ptr, FUTEX_WAKE, 1, 0);
 }
 
 
index 3ef99d5..f51dd0e 100644 (file)
@@ -1,6 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Intel Corporation
 ** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtCore module of the Qt Toolkit.