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:
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<QEventLoopPrivate *>(pointer()); }
QThreadPrivate *thread() const { return static_cast<QThreadPrivate *>(pointer()); }
QCoreApplicationPrivate *app() const { return static_cast<QCoreApplicationPrivate *>(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<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