diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index 4f1077b7125..edde9492f88 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -296,35 +296,11 @@ void QEventLoop::quit() class QEventLoopLockerPrivate { - friend class QEventLoopLocker; public: - explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop) - : QEventLoopLockerPrivate(loop, EventLoop) - { - loop->ref(); - } - - explicit QEventLoopLockerPrivate(QThreadPrivate *thread) - : QEventLoopLockerPrivate(thread, Thread) - { - thread->ref(); - } - - explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app) - : QEventLoopLockerPrivate(app, Application) - { - app->ref(); - } - -private: + using Type = QEventLoopLocker::Type; QEventLoopPrivate *loop() const { return static_cast(pointer()); } QThreadPrivate *thread() const { return static_cast(pointer()); } QCoreApplicationPrivate *app() const { return static_cast(pointer()); } - enum Type { - EventLoop, - Thread, - Application - }; explicit QEventLoopLockerPrivate(void *ptr, Type t) noexcept : p{quintptr(ptr) | quintptr(t)} {} quintptr p; @@ -332,11 +308,19 @@ private: Type type() const { return Type(p & TypeMask); } void *pointer() const { return reinterpret_cast(p & ~TypeMask); } }; +namespace { // If any of these trigger, the Type bits will interfere with the pointer values: static_assert(alignof(QEventLoopPrivate) >= 4); static_assert(alignof(QThreadPrivate) >= 4); static_assert(alignof(QCoreApplicationPrivate) >= 4); +template +Private *o2p(QObject *o) +{ + return static_cast(QObjectPrivate::get(o)); +} +} // unnamed namespace + /*! \class QEventLoopLocker \inmodule QtCore @@ -365,7 +349,8 @@ static_assert(alignof(QCoreApplicationPrivate) >= 4); \sa QCoreApplication::quit(), QCoreApplication::isQuitLockEnabled() */ QEventLoopLocker::QEventLoopLocker() - : d_ptr(new QEventLoopLockerPrivate(static_cast(QObjectPrivate::get(QCoreApplication::instance())))) + : QEventLoopLocker{o2p(QCoreApplication::instance()), + Type::Application} { } @@ -378,7 +363,7 @@ QEventLoopLocker::QEventLoopLocker() \sa QEventLoop::quit() */ QEventLoopLocker::QEventLoopLocker(QEventLoop *loop) - : d_ptr(new QEventLoopLockerPrivate(static_cast(QObjectPrivate::get(loop)))) + : QEventLoopLocker{o2p(loop), Type::EventLoop} { } @@ -391,7 +376,7 @@ QEventLoopLocker::QEventLoopLocker(QEventLoop *loop) \sa QThread::quit() */ QEventLoopLocker::QEventLoopLocker(QThread *thread) - : d_ptr(new QEventLoopLockerPrivate(static_cast(QObjectPrivate::get(thread)))) + : QEventLoopLocker{o2p(thread), Type::Thread} { } @@ -405,6 +390,15 @@ QEventLoopLocker::~QEventLoopLocker() delete d_ptr; } +/*! + \internal +*/ +QEventLoopLocker::QEventLoopLocker(void *ptr, Type t) noexcept + : d_ptr(new QEventLoopLockerPrivate{ptr, t}) +{ + visit([](auto p) { p->ref(); }); +} + /*! \internal */ diff --git a/src/corelib/kernel/qeventloop.h b/src/corelib/kernel/qeventloop.h index 33ab9415e3e..c2b03a94278 100644 --- a/src/corelib/kernel/qeventloop.h +++ b/src/corelib/kernel/qeventloop.h @@ -61,11 +61,18 @@ public: private: Q_DISABLE_COPY(QEventLoopLocker) + friend class QEventLoopLockerPrivate; // // Private implementation details. // Do not call from public inline API! // + enum class Type : quintptr { + EventLoop, + Thread, + Application, + }; + explicit QEventLoopLocker(void *ptr, Type t) noexcept; QEventLoopLockerPrivate *d_ptr; template void visit(Func func) const;