Port QObject::connectImpl() to SlotObjUniquePtr internally

This gets rid of the smell that one destroyIfLastRef() call guarded
against nullptr while the other one did not.

Don't change the function signatures, as passing by unique_ptr, while
making the transfer of ownership clear, makes it impossible to call
the function as a tail-call: Non-trivially-copyable arguments live in
the caller's stack frame and the caller has no idea whether the object
was moved from in the callee or not, so it needs to run the dtor,
which prevents this from being tail-callable.

Passing .release(), OTOH, makes it obvious that the unique_ptr is
nullptr afterwards, so leaves the door open for tail-calling.

However, the QObjectPrivate::connectImpl() wasn't, and continues to
not be, a tail-call. Investigating why, while intriguing, is for
another patch (and much more important for the template wrappers of
these functions than then one out-of-line function we're dealing with
here).

Change-Id: Ib951ed2a2b622d70cb12ddbf01c83ec56b1ce70d
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 93382070183ff5a0bf9a09f7f0e8264472888117)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2023-07-19 21:15:11 +02:00 committed by Qt Cherry-pick Bot
parent 30ffd6639f
commit 8fada6f0c8

View File

@ -5027,13 +5027,12 @@ void qDeleteInEventHandler(QObject *o)
*/
QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal,
const QObject *receiver, void **slot,
QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
QtPrivate::QSlotObjectBase *slotObjRaw, Qt::ConnectionType type,
const int *types, const QMetaObject *senderMetaObject)
{
QtPrivate::SlotObjUniquePtr slotObj(slotObjRaw);
if (!signal) {
qCWarning(lcConnect, "QObject::connect: invalid nullptr parameter");
if (slotObj)
slotObj->destroyIfLastRef();
return QMetaObject::Connection();
}
@ -5046,11 +5045,10 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
}
if (!senderMetaObject) {
qCWarning(lcConnect, "QObject::connect: signal not found in %s", sender->metaObject()->className());
slotObj->destroyIfLastRef();
return QMetaObject::Connection(nullptr);
}
signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject);
return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj.release(), type, types, senderMetaObject);
}
static void connectWarning(const QObject *sender,