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<QEventLoopPrivate, QCoreApplicationPriivate*, QThreadPrivate*>

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 <fabian.kosmale@qt.io>
(cherry picked from commit c70257e9b22226f52caade22b085fb6508fb1ec1)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2023-06-30 17:35:04 +02:00 committed by Qt Cherry-pick Bot
parent 8b1f858f65
commit 3d70617c71

View File

@ -298,52 +298,59 @@ class QEventLoopLockerPrivate
{ {
public: public:
explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop) explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop)
: loop(loop), type(EventLoop) : QEventLoopLockerPrivate(loop, EventLoop)
{ {
loop->ref(); loop->ref();
} }
explicit QEventLoopLockerPrivate(QThreadPrivate *thread) explicit QEventLoopLockerPrivate(QThreadPrivate *thread)
: thread(thread), type(Thread) : QEventLoopLockerPrivate(thread, Thread)
{ {
thread->ref(); thread->ref();
} }
explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app) explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app)
: app(app), type(Application) : QEventLoopLockerPrivate(app, Application)
{ {
app->ref(); app->ref();
} }
~QEventLoopLockerPrivate() ~QEventLoopLockerPrivate()
{ {
switch (type) switch (type())
{ {
case EventLoop: case EventLoop:
loop->deref(); loop()->deref();
break; break;
case Thread: case Thread:
thread->deref(); thread()->deref();
break; break;
default: default:
app->deref(); app()->deref();
break; break;
} }
} }
private: private:
union { QEventLoopPrivate *loop() const { return static_cast<QEventLoopPrivate *>(pointer()); }
QEventLoopPrivate * loop; QThreadPrivate *thread() const { return static_cast<QThreadPrivate *>(pointer()); }
QThreadPrivate * thread; QCoreApplicationPrivate *app() const { return static_cast<QCoreApplicationPrivate *>(pointer()); }
QCoreApplicationPrivate * app;
};
enum Type { enum Type {
EventLoop, EventLoop,
Thread, Thread,
Application 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<void *>(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 \class QEventLoopLocker