From 3d70617c71672f6ed4c5ebe4288df1ca4498ea22 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 30 Jun 2023 17:35:04 +0200 Subject: [PATCH] QEventLoopLockerPrivate: store the tag in the pointer variable There's enough space in the LSB of the three pointers to encode the type. Saves sizeof(void*) in the Private class, but, more importantly, paves the way for the next patch to get rid of the Private class and its memory allocation altogether, turning QEventLoopLocker::d_ptr into what this patch still calls QEventLoopLockerPrivate::p. Neither QTaggedPointer nor QML's QBiPointer apply here. QTaggedPointer only supports a single T, plus flags; QBiPointer supports only two Ts, and one flag; we need three Ts and no flags. This could be a QVariantPointer I'm thinking about it; just would want to find a second use-case for it. Task-number: QTBUG-114793 Change-Id: I0e21bd8745cc75a9c04b71343c398ad953283857 Reviewed-by: Fabian Kosmale (cherry picked from commit c70257e9b22226f52caade22b085fb6508fb1ec1) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qeventloop.cpp | 33 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index 7001bfa5bd5..a29f79e86a9 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -298,52 +298,59 @@ class QEventLoopLockerPrivate { public: explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop) - : loop(loop), type(EventLoop) + : QEventLoopLockerPrivate(loop, EventLoop) { loop->ref(); } explicit QEventLoopLockerPrivate(QThreadPrivate *thread) - : thread(thread), type(Thread) + : QEventLoopLockerPrivate(thread, Thread) { thread->ref(); } explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app) - : app(app), type(Application) + : QEventLoopLockerPrivate(app, Application) { app->ref(); } ~QEventLoopLockerPrivate() { - switch (type) + switch (type()) { case EventLoop: - loop->deref(); + loop()->deref(); break; case Thread: - thread->deref(); + thread()->deref(); break; default: - app->deref(); + app()->deref(); break; } } private: - union { - QEventLoopPrivate * loop; - QThreadPrivate * thread; - QCoreApplicationPrivate * app; - }; + 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 }; - const Type type; + explicit QEventLoopLockerPrivate(void *ptr, Type t) noexcept + : p{quintptr(ptr) | quintptr(t)} {} + quintptr p; + static constexpr quintptr TypeMask = 0x3; + Type type() const { return Type(p & TypeMask); } + void *pointer() const { return reinterpret_cast(p & ~TypeMask); } }; +// 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); /*! \class QEventLoopLocker