QReadWriteLock: remove the private function from the symbol table

Just move it to the private class. This also allows this function to get
inlined in QWaitCondition::wait().

Change-Id: I6f518d59e63249ddbf43fffd1759fc99c28c7ca8
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit 0c0778fb36641efe73caa8776ee0a2ffdc98f4ea)
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
This commit is contained in:
Thiago Macieira 2023-04-27 20:47:53 -07:00
parent e885a06390
commit ac111209f8
5 changed files with 56 additions and 41 deletions

View File

@ -6,9 +6,7 @@
#include "qplatformdefs.h" #include "qplatformdefs.h"
#include "qreadwritelock.h" #include "qreadwritelock.h"
#include "qmutex.h"
#include "qthread.h" #include "qthread.h"
#include "qwaitcondition.h"
#include "qreadwritelock_p.h" #include "qreadwritelock_p.h"
#include "qelapsedtimer.h" #include "qelapsedtimer.h"
#include "private/qfreelist_p.h" #include "private/qfreelist_p.h"
@ -30,15 +28,11 @@ QT_BEGIN_NAMESPACE
* - In any other case, d_ptr points to an actual QReadWriteLockPrivate. * - In any other case, d_ptr points to an actual QReadWriteLockPrivate.
*/ */
using namespace QReadWriteLockStates;
namespace { namespace {
using ms = std::chrono::milliseconds; using ms = std::chrono::milliseconds;
enum {
StateMask = 0x3,
StateLockedForRead = 0x1,
StateLockedForWrite = 0x2,
};
const auto dummyLockedForRead = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForRead)); const auto dummyLockedForRead = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForRead));
const auto dummyLockedForWrite = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForWrite)); const auto dummyLockedForWrite = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForWrite));
inline bool isUncontendedLocked(const QReadWriteLockPrivate *d) inline bool isUncontendedLocked(const QReadWriteLockPrivate *d)
@ -411,26 +405,6 @@ void QReadWriteLock::unlock()
} }
} }
/*! \internal Helper for QWaitCondition::wait */
QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() const
{
QReadWriteLockPrivate *d = d_ptr.loadAcquire();
switch (quintptr(d) & StateMask) {
case StateLockedForRead: return LockedForRead;
case StateLockedForWrite: return LockedForWrite;
}
if (!d)
return Unlocked;
const auto lock = qt_scoped_lock(d->mutex);
if (d->writerCount > 1)
return RecursivelyLocked;
else if (d->writerCount == 1)
return LockedForWrite;
return LockedForRead;
}
bool QReadWriteLockPrivate::lockForRead(std::unique_lock<QtPrivate::mutex> &lock, int timeout) bool QReadWriteLockPrivate::lockForRead(std::unique_lock<QtPrivate::mutex> &lock, int timeout)
{ {
Q_ASSERT(!mutex.try_lock()); // mutex must be locked when entering this function Q_ASSERT(!mutex.try_lock()); // mutex must be locked when entering this function

View File

@ -34,10 +34,7 @@ public:
private: private:
Q_DISABLE_COPY(QReadWriteLock) Q_DISABLE_COPY(QReadWriteLock)
QAtomicPointer<QReadWriteLockPrivate> d_ptr; QAtomicPointer<QReadWriteLockPrivate> d_ptr;
friend class QReadWriteLockPrivate;
enum StateForWaitCondition { LockedForRead, LockedForWrite, Unlocked, RecursivelyLocked };
StateForWaitCondition stateForWaitCondition() const;
friend class QWaitCondition;
}; };
#if defined(Q_CC_MSVC) #if defined(Q_CC_MSVC)

View File

@ -16,14 +16,29 @@
// We mean it. // We mean it.
// //
#include <QtCore/private/qglobal_p.h> #include <QtCore/private/qlocking_p.h>
#include <QtCore/private/qwaitcondition_p.h> #include <QtCore/private/qwaitcondition_p.h>
#include <QtCore/qreadwritelock.h>
#include <QtCore/qvarlengtharray.h> #include <QtCore/qvarlengtharray.h>
QT_REQUIRE_CONFIG(thread); QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace QReadWriteLockStates {
enum {
StateMask = 0x3,
StateLockedForRead = 0x1,
StateLockedForWrite = 0x2,
};
enum StateForWaitCondition {
LockedForRead,
LockedForWrite,
Unlocked,
RecursivelyLocked
};
}
class QReadWriteLockPrivate class QReadWriteLockPrivate
{ {
public: public:
@ -63,8 +78,33 @@ public:
bool recursiveLockForWrite(int timeout); bool recursiveLockForWrite(int timeout);
bool recursiveLockForRead(int timeout); bool recursiveLockForRead(int timeout);
void recursiveUnlock(); void recursiveUnlock();
static QReadWriteLockStates::StateForWaitCondition
stateForWaitCondition(const QReadWriteLock *lock);
}; };
Q_DECLARE_TYPEINFO(QReadWriteLockPrivate::Reader, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(QReadWriteLockPrivate::Reader, Q_PRIMITIVE_TYPE);\
/*! \internal Helper for QWaitCondition::wait */
inline QReadWriteLockStates::StateForWaitCondition
QReadWriteLockPrivate::stateForWaitCondition(const QReadWriteLock *q)
{
using namespace QReadWriteLockStates;
QReadWriteLockPrivate *d = q->d_ptr.loadAcquire();
switch (quintptr(d) & StateMask) {
case StateLockedForRead: return LockedForRead;
case StateLockedForWrite: return LockedForWrite;
}
if (!d)
return Unlocked;
const auto lock = qt_scoped_lock(d->mutex);
if (d->writerCount > 1)
return RecursivelyLocked;
else if (d->writerCount == 1)
return LockedForWrite;
return LockedForRead;
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -173,12 +173,14 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline) bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline)
{ {
using namespace QReadWriteLockStates;
if (!readWriteLock) if (!readWriteLock)
return false; return false;
auto previousState = readWriteLock->stateForWaitCondition(); auto previousState = QReadWriteLockPrivate::stateForWaitCondition(readWriteLock);
if (previousState == QReadWriteLock::Unlocked) if (previousState == Unlocked)
return false; return false;
if (previousState == QReadWriteLock::RecursivelyLocked) { if (previousState == RecursivelyLocked) {
qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()"); qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
return false; return false;
} }
@ -190,7 +192,7 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline
bool returnValue = d->wait(deadline); bool returnValue = d->wait(deadline);
if (previousState == QReadWriteLock::LockedForWrite) if (previousState == LockedForWrite)
readWriteLock->lockForWrite(); readWriteLock->lockForWrite();
else else
readWriteLock->lockForRead(); readWriteLock->lockForRead();

View File

@ -145,12 +145,14 @@ bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
{ {
using namespace QReadWriteLockStates;
if (!readWriteLock) if (!readWriteLock)
return false; return false;
auto previousState = readWriteLock->stateForWaitCondition(); auto previousState = QReadWriteLockPrivate::stateForWaitCondition(readWriteLock);
if (previousState == QReadWriteLock::Unlocked) if (previousState == Unlocked)
return false; return false;
if (previousState == QReadWriteLock::RecursivelyLocked) { if (previousState == RecursivelyLocked) {
qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()"); qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
return false; return false;
} }
@ -160,7 +162,7 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
bool returnValue = d->wait(wce, time); bool returnValue = d->wait(wce, time);
if (previousState == QReadWriteLock::LockedForWrite) if (previousState == LockedForWrite)
readWriteLock->lockForWrite(); readWriteLock->lockForWrite();
else else
readWriteLock->lockForRead(); readWriteLock->lockForRead();