if (c->next) c->next->prev = c->prev;
}
if (needToUnlock)
- m->unlockInline();
+ m->unlock();
connectionList.first = c->nextConnectionList;
delete c;
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
//the node has maybe been removed while the mutex was unlocked in relock?
if (!node || node->sender != sender) {
- m->unlockInline();
+ m->unlock();
continue;
}
node->receiver = 0;
node = node->next;
if (needToUnlock)
- m->unlockInline();
+ m->unlock();
}
}
}
if (needToUnlock)
- receiverMutex->unlockInline();
+ receiverMutex->unlock();
c->receiver = 0;
#include <qdebug.h>
#ifndef QT_NO_THREAD
-#include "qatomic.h"
-#include "qelapsedtimer.h"
-#include "qthread.h"
#include "qmutex_p.h"
QT_BEGIN_NAMESPACE
+QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
+ : recursive(mode == QMutex::Recursive)
+{
+}
+
/*!
\class QMutex
\brief The QMutex class provides access serialization between threads.
void QMutex::lock()
{
QMutexPrivate *d = this->d;
-
if (d->recursive) {
- Qt::HANDLE self = QThread::currentThreadId();
- if (d->owner == self) {
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::lock", "Overflow in recursion counter");
- return;
- }
-
- 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.");
- }
-
- d->owner = self;
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::lock", "Overflow in recursion counter");
- return;
- }
-
- bool isLocked = d->contenders.testAndSetAcquire(0, 1);
- if (!isLocked) {
- lockInternal();
+ d->mutex2.lock();
+ } else {
+ d->mutex1.lock();
}
}
bool QMutex::tryLock()
{
QMutexPrivate *d = this->d;
-
if (d->recursive) {
- Qt::HANDLE self = QThread::currentThreadId();
- if (d->owner == self) {
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
- return true;
- }
-
- 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
- return isLocked;
- }
-
- d->owner = self;
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
- return isLocked;
+ return d->mutex2.try_lock();
+ } else {
+ return d->mutex1.try_lock();
}
-
- return d->contenders.testAndSetAcquire(0, 1);
}
/*! \overload
bool QMutex::tryLock(int timeout)
{
QMutexPrivate *d = this->d;
-
if (d->recursive) {
- Qt::HANDLE self = QThread::currentThreadId();
- if (d->owner == self) {
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
- return true;
- }
-
- bool isLocked = d->contenders.testAndSetAcquire(0, 1);
- if (!isLocked) {
- // didn't get the lock, wait for it
- isLocked = d->wait(timeout);
- if (!isLocked)
- return false;
- }
-
- d->owner = self;
- ++d->count;
- Q_ASSERT_X(d->count != 0, "QMutex::tryLock", "Overflow in recursion counter");
- return true;
+ return d->mutex2.try_lock_for(std::chrono::milliseconds(timeout));
+ } else {
+ return d->mutex1.try_lock_for(std::chrono::milliseconds(timeout));
}
-
- return (d->contenders.testAndSetAcquire(0, 1)
- // didn't get the lock, wait for it
- || d->wait(timeout));
}
{
QMutexPrivate *d = this->d;
if (d->recursive) {
- if (!--d->count) {
- d->owner = 0;
- if (!d->contenders.testAndSetRelease(1, 0))
- d->wakeUp();
- }
+ d->mutex2.unlock();
} else {
- if (!d->contenders.testAndSetRelease(1, 0))
- d->wakeUp();
+ d->mutex1.unlock();
}
}
Use the constructor that takes a RecursionMode parameter instead.
*/
-/*!
- \internal helper for lockInline()
- */
-void QMutex::lockInternal()
-{
- QMutexPrivate *d = this->d;
-
- if (QThread::idealThreadCount() == 1) {
- // don't spin on single cpu machines
- bool isLocked = d->wait();
- Q_ASSERT_X(isLocked, "QMutex::lock",
- "Internal error, infinite wait has timed out.");
- Q_UNUSED(isLocked);
- return;
- }
-
- QElapsedTimer elapsedTimer;
- elapsedTimer.start();
- do {
- qint64 spinTime = elapsedTimer.nsecsElapsed();
- if (spinTime > d->maximumSpinTime) {
- // didn't get the lock, wait for it, since we're not going to gain anything by spinning more
- elapsedTimer.start();
- bool isLocked = d->wait();
- Q_ASSERT_X(isLocked, "QMutex::lock",
- "Internal error, infinite wait has timed out.");
- Q_UNUSED(isLocked);
-
- qint64 maximumSpinTime = d->maximumSpinTime;
- qint64 averageWaitTime = d->averageWaitTime;
- qint64 actualWaitTime = elapsedTimer.nsecsElapsed();
- if (actualWaitTime < (QMutexPrivate::MaximumSpinTimeThreshold * 3 / 2)) {
- // measure the wait times
- averageWaitTime = d->averageWaitTime = qMin((averageWaitTime + actualWaitTime) / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
- }
-
- // adjust the spin count when spinning does not benefit contention performance
- if ((spinTime + actualWaitTime) - qint64(QMutexPrivate::MaximumSpinTimeThreshold) >= qint64(QMutexPrivate::MaximumSpinTimeThreshold)) {
- // long waits, stop spinning
- d->maximumSpinTime = 0;
- } else {
- // allow spinning if wait times decrease, but never spin more than the average wait time (otherwise we may perform worse)
- d->maximumSpinTime = qBound(qint64(averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
- }
- return;
- }
- // be a good citizen... yielding lets something else run if there is something to run, but may also relieve memory pressure if not
- QThread::yieldCurrentThread();
- } while (d->contenders != 0 || !d->contenders.testAndSetAcquire(0, 1));
-
- // spinning is working, do not change the spin time (unless we are using much less time than allowed to spin)
- qint64 maximumSpinTime = d->maximumSpinTime;
- qint64 spinTime = elapsedTimer.nsecsElapsed();
- if (spinTime < maximumSpinTime / 2) {
- // we are using much less time than we need, adjust the limit
- d->maximumSpinTime = qBound(qint64(d->averageWaitTime * 3 / 2), maximumSpinTime / 2, qint64(QMutexPrivate::MaximumSpinTimeThreshold));
- }
-}
-
-
-/*!
- \fn QMutex::lockInline()
- \internal
- inline version of QMutex::lock()
-*/
-
-/*!
- \fn QMutex::unlockInline()
- \internal
- inline version of QMutex::unlock()
-*/
-
-/*!
- \fn QMutex::tryLockInline()
- \internal
- inline version of QMutex::tryLock()
-*/
-
-
QT_END_NAMESPACE
#endif // QT_NO_THREAD
friend class QWaitConditionPrivate;
public:
- enum RecursionMode { NonRecursive, Recursive };
+ enum RecursionMode {
+ NonRecursive,
+ Recursive
+ };
explicit QMutex(RecursionMode mode = NonRecursive);
~QMutex();
void lock();
- inline void unlockInline() { unlock(); }
bool tryLock();
bool tryLock(int timeout);
- inline bool tryLockInline() { return tryLock(); }
void unlock();
- inline void lockInline() { lock(); }
-
private:
- void lockInternal();
Q_DISABLE_COPY(QMutex)
QMutexPrivate *d;
inline ~QMutex() {}
static inline void lock() {}
- static inline void lockInline() {}
static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; }
- static inline bool tryLockInline() { return true; }
static inline void unlock() {}
- static inline void unlockInline() {}
-
private:
Q_DISABLE_COPY(QMutex)
#include <QtCore/qnamespace.h>
#include <QtCore/qmutex.h>
+#include <mutex>
QT_BEGIN_NAMESPACE
class QMutexPrivate {
public:
QMutexPrivate(QMutex::RecursionMode mode);
- ~QMutexPrivate();
- bool wait(int timeout = -1);
- void wakeUp();
-
- // 1ms = 1000000ns
- enum { MaximumSpinTimeThreshold = 1000000 };
- volatile qint64 maximumSpinTime;
- volatile qint64 averageWaitTime;
- Qt::HANDLE owner;
- uint count;
const bool recursive;
- QAtomicInt contenders;
-
- volatile bool wakeup;
- pthread_mutex_t mutex;
- pthread_cond_t cond;
+ std::timed_mutex mutex1;
+ std::recursive_timed_mutex mutex2;
};
QT_END_NAMESPACE
+++ /dev/null
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformdefs.h"
-#include "qmutex.h"
-#include "qstring.h"
-
-#ifndef QT_NO_THREAD
-#include "qatomic.h"
-#include "qmutex_p.h"
-#include "qcorecommon_p.h"
-
-#include <errno.h>
-
-QT_BEGIN_NAMESPACE
-
-QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
- : maximumSpinTime(MaximumSpinTimeThreshold), averageWaitTime(0), owner(0), count(0), recursive(mode == QMutex::Recursive)
-{
- wakeup = false;
- report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
- report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
-}
-
-QMutexPrivate::~QMutexPrivate()
-{
- report_error(pthread_cond_destroy(&cond), "QMutex", "cv destroy");
- report_error(pthread_mutex_destroy(&mutex), "QMutex", "mutex destroy");
-}
-
-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) {
- if (timeout < 0) {
- errorCode = pthread_cond_wait(&cond, &mutex);
- } else {
- struct timeval tv;
- gettimeofday(&tv, Q_NULLPTR);
-
- timespec ti;
- ti.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000) * 1000;
- ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
- ti.tv_nsec %= 1000000000;
-
- errorCode = pthread_cond_timedwait(&cond, &mutex, &ti);
- }
- if (errorCode) {
- if (errorCode == ETIMEDOUT) {
- if (wakeup)
- errorCode = 0;
- break;
- }
- report_error(errorCode, "QMutex::lock()", "cv wait");
- }
- }
- wakeup = false;
- report_error(pthread_mutex_unlock(&mutex), "QMutex::lock", "mutex unlock");
- contenders.deref();
- return errorCode == 0;
-}
-
-void QMutexPrivate::wakeUp()
-{
- report_error(pthread_mutex_lock(&mutex), "QMutex::unlock", "mutex lock");
- wakeup = true;
- report_error(pthread_cond_signal(&cond), "QMutex::unlock", "cv signal");
- report_error(pthread_mutex_unlock(&mutex), "QMutex::unlock", "mutex unlock");
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_THREAD
void relock()
{
if (!locked) {
- if (mtx1) mtx1->lockInline();
- if (mtx2) mtx2->lockInline();
+ if (mtx1) mtx1->lock();
+ if (mtx2) mtx2->lock();
locked = true;
}
}
void unlock()
{
if (locked) {
- if (mtx1) mtx1->unlockInline();
- if (mtx2) mtx2->unlockInline();
+ if (mtx1) mtx1->unlock();
+ if (mtx2) mtx2->unlock();
locked = false;
}
}
if (mtx1 == mtx2)
return false;
if (mtx1 < mtx2) {
- mtx2->lockInline();
+ mtx2->lock();
return true;
}
- if (!mtx2->tryLockInline()) {
+ if (!mtx2->tryLock()) {
mtx1->unlock();
mtx2->lock();
mtx1->lock();
${CMAKE_CURRENT_SOURCE_DIR}/thread/qmutexpool.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread/qsemaphore.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread/qthread.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/thread/qmutex_unix.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread/qthread_unix.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread/qwaitcondition_unix.cpp
)