Refactor QMutexLocker to be able to handle recursive mutexes
Since we're going to split QMutex and QRecursiveMutex into separate classes, make sure QMutexLocker is prepared for that. Change-Id: Id5e9a955d1db7c8ee663dd3811ad6448dad0aeae Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
f76530a617
commit
77d812683f
@ -147,7 +147,7 @@ public:
|
|||||||
inline Value prepareValue(const QString &value) const { return value; }
|
inline Value prepareValue(const QString &value) const { return value; }
|
||||||
inline QString valueToString(const Value &value) const { return value; }
|
inline QString valueToString(const Value &value) const { return value; }
|
||||||
#else
|
#else
|
||||||
struct NameMapMutexLocker : public QMutexLocker
|
struct NameMapMutexLocker : public QMutexLocker<QMutex>
|
||||||
{
|
{
|
||||||
NameMapMutexLocker(const QProcessEnvironmentPrivate *d) : QMutexLocker(&d->nameMapMutex) {}
|
NameMapMutexLocker(const QProcessEnvironmentPrivate *d) : QMutexLocker(&d->nameMapMutex) {}
|
||||||
};
|
};
|
||||||
|
@ -179,10 +179,10 @@ int QEventLoop::exec(ProcessEventsFlags flags)
|
|||||||
|
|
||||||
struct LoopReference {
|
struct LoopReference {
|
||||||
QEventLoopPrivate *d;
|
QEventLoopPrivate *d;
|
||||||
QMutexLocker &locker;
|
QMutexLocker<QMutex> &locker;
|
||||||
|
|
||||||
bool exceptionCaught;
|
bool exceptionCaught;
|
||||||
LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
|
LoopReference(QEventLoopPrivate *d, QMutexLocker<QMutex> &locker) : d(d), locker(locker), exceptionCaught(true)
|
||||||
{
|
{
|
||||||
d->inExec = true;
|
d->inExec = true;
|
||||||
d->exit.storeRelease(false);
|
d->exit.storeRelease(false);
|
||||||
|
@ -601,7 +601,7 @@ int QtAndroidPrivate::acuqireServiceSetup(int flags)
|
|||||||
|
|
||||||
void QtAndroidPrivate::setOnBindListener(QtAndroidPrivate::OnBindListener *listener)
|
void QtAndroidPrivate::setOnBindListener(QtAndroidPrivate::OnBindListener *listener)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(g_onBindListenerMutex);
|
QMutexLocker lock(g_onBindListenerMutex());
|
||||||
*g_onBindListener = listener;
|
*g_onBindListener = listener;
|
||||||
if (!g_serviceSetupLockers->deref())
|
if (!g_serviceSetupLockers->deref())
|
||||||
g_waitForServiceSetupSemaphore->release();
|
g_waitForServiceSetupSemaphore->release();
|
||||||
@ -609,7 +609,7 @@ void QtAndroidPrivate::setOnBindListener(QtAndroidPrivate::OnBindListener *liste
|
|||||||
|
|
||||||
jobject QtAndroidPrivate::callOnBindListener(jobject intent)
|
jobject QtAndroidPrivate::callOnBindListener(jobject intent)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(g_onBindListenerMutex);
|
QMutexLocker lock(g_onBindListenerMutex());
|
||||||
if (*g_onBindListener)
|
if (*g_onBindListener)
|
||||||
return (*g_onBindListener)->onBind(intent);
|
return (*g_onBindListener)->onBind(intent);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -423,7 +423,7 @@ QRecursiveMutex::~QRecursiveMutex()
|
|||||||
|
|
||||||
\ingroup thread
|
\ingroup thread
|
||||||
|
|
||||||
Locking and unlocking a QMutex in complex functions and
|
Locking and unlocking a QMutex or QRecursiveMutex in complex functions and
|
||||||
statements or in exception handling code is error-prone and
|
statements or in exception handling code is error-prone and
|
||||||
difficult to debug. QMutexLocker can be used in such situations
|
difficult to debug. QMutexLocker can be used in such situations
|
||||||
to ensure that the state of the mutex is always well-defined.
|
to ensure that the state of the mutex is always well-defined.
|
||||||
|
@ -174,6 +174,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QMutex)
|
Q_DISABLE_COPY(QMutex)
|
||||||
|
template<typename Mutex>
|
||||||
friend class QMutexLocker;
|
friend class QMutexLocker;
|
||||||
friend class QRecursiveMutex;
|
friend class QRecursiveMutex;
|
||||||
friend class ::tst_QMutex;
|
friend class ::tst_QMutex;
|
||||||
@ -207,6 +208,7 @@ private:
|
|||||||
class QRecursiveMutex : private QMutex
|
class QRecursiveMutex : private QMutex
|
||||||
{
|
{
|
||||||
// ### Qt 6: make it independent of QMutex
|
// ### Qt 6: make it independent of QMutex
|
||||||
|
template<typename Mutex>
|
||||||
friend class QMutexLocker;
|
friend class QMutexLocker;
|
||||||
public:
|
public:
|
||||||
Q_CORE_EXPORT QRecursiveMutex();
|
Q_CORE_EXPORT QRecursiveMutex();
|
||||||
@ -222,65 +224,49 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class Q_CORE_EXPORT QMutexLocker
|
template <typename Mutex>
|
||||||
|
class QMutexLocker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#ifndef Q_CLANG_QDOC
|
inline explicit QMutexLocker(Mutex *mutex) QT_MUTEX_LOCK_NOEXCEPT
|
||||||
inline explicit QMutexLocker(QBasicMutex *m) QT_MUTEX_LOCK_NOEXCEPT
|
|
||||||
{
|
{
|
||||||
Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0),
|
m = mutex;
|
||||||
"QMutexLocker", "QMutex pointer is misaligned");
|
if (Q_LIKELY(mutex)) {
|
||||||
val = quintptr(m);
|
mutex->lock();
|
||||||
if (Q_LIKELY(m)) {
|
isLocked = true;
|
||||||
// call QMutex::lock() instead of QBasicMutex::lock()
|
|
||||||
static_cast<QMutex *>(m)->lock();
|
|
||||||
val |= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
explicit QMutexLocker(QRecursiveMutex *m) QT_MUTEX_LOCK_NOEXCEPT
|
inline ~QMutexLocker() {
|
||||||
: QMutexLocker{static_cast<QBasicMutex*>(m)} {}
|
unlock();
|
||||||
#else
|
}
|
||||||
QMutexLocker(QMutex *) { }
|
|
||||||
QMutexLocker(QRecursiveMutex *) {}
|
|
||||||
#endif
|
|
||||||
inline ~QMutexLocker() { unlock(); }
|
|
||||||
|
|
||||||
inline void unlock() noexcept
|
inline void unlock() noexcept
|
||||||
{
|
{
|
||||||
if ((val & quintptr(1u)) == quintptr(1u)) {
|
if (!isLocked)
|
||||||
val &= ~quintptr(1u);
|
return;
|
||||||
mutex()->unlock();
|
m->unlock();
|
||||||
}
|
isLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void relock() QT_MUTEX_LOCK_NOEXCEPT
|
inline void relock() QT_MUTEX_LOCK_NOEXCEPT
|
||||||
{
|
{
|
||||||
if (val) {
|
if (isLocked)
|
||||||
if ((val & quintptr(1u)) == quintptr(0u)) {
|
return;
|
||||||
mutex()->lock();
|
if (m) {
|
||||||
val |= quintptr(1u);
|
m->lock();
|
||||||
}
|
isLocked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_CC_MSVC)
|
Mutex *mutex() const
|
||||||
#pragma warning( push )
|
|
||||||
#pragma warning( disable : 4312 ) // ignoring the warning from /Wp64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline QMutex *mutex() const
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<QMutex *>(val & ~quintptr(1u));
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_CC_MSVC)
|
|
||||||
#pragma warning( pop )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QMutexLocker)
|
Q_DISABLE_COPY(QMutexLocker)
|
||||||
|
|
||||||
quintptr val;
|
Mutex *m;
|
||||||
|
bool isLocked = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else // !QT_CONFIG(thread) && !Q_CLANG_QDOC
|
#else // !QT_CONFIG(thread) && !Q_CLANG_QDOC
|
||||||
@ -320,15 +306,16 @@ private:
|
|||||||
|
|
||||||
class QRecursiveMutex : public QMutex {};
|
class QRecursiveMutex : public QMutex {};
|
||||||
|
|
||||||
class Q_CORE_EXPORT QMutexLocker
|
template<typename Mutex>
|
||||||
|
class QMutexLocker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline explicit QMutexLocker(QMutex *) noexcept {}
|
inline explicit QMutexLocker(Mutex *) noexcept {}
|
||||||
inline ~QMutexLocker() noexcept {}
|
inline ~QMutexLocker() noexcept {}
|
||||||
|
|
||||||
inline void unlock() noexcept {}
|
inline void unlock() noexcept {}
|
||||||
void relock() noexcept {}
|
void relock() noexcept {}
|
||||||
inline QMutex *mutex() const noexcept { return nullptr; }
|
inline Mutex *mutex() const noexcept { return nullptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(QMutexLocker)
|
Q_DISABLE_COPY(QMutexLocker)
|
||||||
|
@ -162,7 +162,7 @@ public:
|
|||||||
static bool relock(QBasicMutex *, QBasicMutex *) { return false; }
|
static bool relock(QBasicMutex *, QBasicMutex *) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
using QBasicMutexLocker = QMutexLocker;
|
using QBasicMutexLocker = QMutexLocker<QBasicMutex>;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -314,7 +314,7 @@ OSStatus QSslSocketBackendPrivate::WriteCallback(QSslSocketBackendPrivate *socke
|
|||||||
|
|
||||||
void QSslSocketPrivate::ensureInitialized()
|
void QSslSocketPrivate::ensureInitialized()
|
||||||
{
|
{
|
||||||
const QMutexLocker locker(qt_securetransport_mutex);
|
const QMutexLocker locker(qt_securetransport_mutex());
|
||||||
if (s_loadedCiphersAndCerts)
|
if (s_loadedCiphersAndCerts)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2233,7 +2233,7 @@ bool QSslSocketPrivate::ensureLibraryLoaded()
|
|||||||
if (!q_resolveOpenSslSymbols())
|
if (!q_resolveOpenSslSymbols())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QMutexLocker locker(qt_opensslInitMutex);
|
const QMutexLocker locker(qt_opensslInitMutex());
|
||||||
|
|
||||||
if (!s_libraryLoaded) {
|
if (!s_libraryLoaded) {
|
||||||
// Initialize OpenSSL.
|
// Initialize OpenSSL.
|
||||||
@ -2265,7 +2265,7 @@ bool QSslSocketPrivate::ensureLibraryLoaded()
|
|||||||
|
|
||||||
void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
|
void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
|
||||||
{
|
{
|
||||||
const QMutexLocker locker(qt_opensslInitMutex);
|
const QMutexLocker locker(qt_opensslInitMutex());
|
||||||
|
|
||||||
if (s_loadedCiphersAndCerts)
|
if (s_loadedCiphersAndCerts)
|
||||||
return;
|
return;
|
||||||
|
@ -103,7 +103,7 @@ void tst_QReadWriteLock::uncontended_data()
|
|||||||
QTest::addColumn<FunctionPtrHolder>("holder");
|
QTest::addColumn<FunctionPtrHolder>("holder");
|
||||||
|
|
||||||
QTest::newRow("nothing") << FunctionPtrHolder(testUncontended<int, FakeLock>);
|
QTest::newRow("nothing") << FunctionPtrHolder(testUncontended<int, FakeLock>);
|
||||||
QTest::newRow("QMutex") << FunctionPtrHolder(testUncontended<QMutex, QMutexLocker>);
|
QTest::newRow("QMutex") << FunctionPtrHolder(testUncontended<QMutex, QMutexLocker<QMutex>>);
|
||||||
QTest::newRow("QReadWriteLock, read")
|
QTest::newRow("QReadWriteLock, read")
|
||||||
<< FunctionPtrHolder(testUncontended<QReadWriteLock, QReadLocker>);
|
<< FunctionPtrHolder(testUncontended<QReadWriteLock, QReadLocker>);
|
||||||
QTest::newRow("QReadWriteLock, write")
|
QTest::newRow("QReadWriteLock, write")
|
||||||
@ -173,7 +173,7 @@ void tst_QReadWriteLock::readOnly_data()
|
|||||||
QTest::addColumn<FunctionPtrHolder>("holder");
|
QTest::addColumn<FunctionPtrHolder>("holder");
|
||||||
|
|
||||||
QTest::newRow("nothing") << FunctionPtrHolder(testReadOnly<int, FakeLock>);
|
QTest::newRow("nothing") << FunctionPtrHolder(testReadOnly<int, FakeLock>);
|
||||||
QTest::newRow("QMutex") << FunctionPtrHolder(testReadOnly<QMutex, QMutexLocker>);
|
QTest::newRow("QMutex") << FunctionPtrHolder(testReadOnly<QMutex, QMutexLocker<QMutex>>);
|
||||||
QTest::newRow("QReadWriteLock") << FunctionPtrHolder(testReadOnly<QReadWriteLock, QReadLocker>);
|
QTest::newRow("QReadWriteLock") << FunctionPtrHolder(testReadOnly<QReadWriteLock, QReadLocker>);
|
||||||
QTest::newRow("std::mutex") << FunctionPtrHolder(
|
QTest::newRow("std::mutex") << FunctionPtrHolder(
|
||||||
testReadOnly<std::mutex, LockerWrapper<std::unique_lock<std::mutex>>>);
|
testReadOnly<std::mutex, LockerWrapper<std::unique_lock<std::mutex>>>);
|
||||||
@ -234,7 +234,7 @@ void tst_QReadWriteLock::writeOnly_data()
|
|||||||
QTest::addColumn<FunctionPtrHolder>("holder");
|
QTest::addColumn<FunctionPtrHolder>("holder");
|
||||||
|
|
||||||
// QTest::newRow("nothing") << FunctionPtrHolder(testWriteOnly<int, FakeLock>);
|
// QTest::newRow("nothing") << FunctionPtrHolder(testWriteOnly<int, FakeLock>);
|
||||||
QTest::newRow("QMutex") << FunctionPtrHolder(testWriteOnly<QMutex, QMutexLocker>);
|
QTest::newRow("QMutex") << FunctionPtrHolder(testWriteOnly<QMutex, QMutexLocker<QMutex>>);
|
||||||
QTest::newRow("QReadWriteLock") << FunctionPtrHolder(testWriteOnly<QReadWriteLock, QWriteLocker>);
|
QTest::newRow("QReadWriteLock") << FunctionPtrHolder(testWriteOnly<QReadWriteLock, QWriteLocker>);
|
||||||
QTest::newRow("std::mutex") << FunctionPtrHolder(
|
QTest::newRow("std::mutex") << FunctionPtrHolder(
|
||||||
testWriteOnly<std::mutex, LockerWrapper<std::unique_lock<std::mutex>>>);
|
testWriteOnly<std::mutex, LockerWrapper<std::unique_lock<std::mutex>>>);
|
||||||
|
@ -110,7 +110,7 @@ void tst_QWaitCondition::oscillate_mutex_data()
|
|||||||
void tst_QWaitCondition::oscillate_mutex()
|
void tst_QWaitCondition::oscillate_mutex()
|
||||||
{
|
{
|
||||||
QFETCH(unsigned long, timeout);
|
QFETCH(unsigned long, timeout);
|
||||||
oscillate<QMutex, QMutexLocker>(timeout);
|
oscillate<QMutex, QMutexLocker<QMutex>>(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QWaitCondition::oscillate_writelock_data()
|
void tst_QWaitCondition::oscillate_writelock_data()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user