diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 5a32c6f2147..9269e3b6cd9 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -551,7 +551,7 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, const QObject *sender, int signalId, void **args, QSemaphore *semaphore) : QAbstractMetaCallEvent(sender, signalId, semaphore), - d({slotO, args, nullptr, 0, 0, ushort(-1)}), + d({QtPrivate::SlotObjUniquePtr{slotO}, args, nullptr, 0, 0, ushort(-1)}), prealloc_() { if (d.slotObj_) @@ -585,7 +585,7 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, const QObject *sender, int signalId, int nargs) : QAbstractMetaCallEvent(sender, signalId), - d({slotO, nullptr, nullptr, nargs, 0, ushort(-1)}), + d({QtPrivate::SlotObjUniquePtr(slotO), nullptr, nullptr, nargs, 0, ushort(-1)}), prealloc_() { if (d.slotObj_) @@ -607,8 +607,6 @@ QMetaCallEvent::~QMetaCallEvent() if (reinterpret_cast(d.args_) != reinterpret_cast(prealloc_)) free(d.args_); } - if (d.slotObj_) - d.slotObj_->destroyIfLastRef(); } /*! diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 5fcf138b443..937ac59f8eb 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -420,7 +420,7 @@ private: inline void allocArgs(); struct Data { - QtPrivate::QSlotObjectBase *slotObj_; + QtPrivate::SlotObjUniquePtr slotObj_; void **args_; QObjectPrivate::StaticMetaCallFunction callFunction_; int nargs_; diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index 6f2dac783be..a9503595b2a 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -14,6 +14,8 @@ #include +#include + QT_BEGIN_NAMESPACE class QObject; class QObjectPrivate; @@ -413,6 +415,15 @@ namespace QtPrivate { public: explicit QSlotObjectBase(ImplFn fn) : m_impl(fn) {} + // A custom deleter compatible with std protocols (op()()) we well as + // the legacy QScopedPointer protocol (cleanup()). + struct Deleter { + void operator()(QSlotObjectBase *p) const noexcept + { if (p) p->destroyIfLastRef(); } + // for the non-standard QScopedPointer protocol: + static void cleanup(QSlotObjectBase *p) noexcept { Deleter{}(p); } + }; + inline int ref() noexcept { return m_ref.ref(); } #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) inline void destroyIfLastRef() noexcept @@ -439,6 +450,9 @@ namespace QtPrivate { Q_DISABLE_COPY_MOVE(QSlotObjectBase) }; + using SlotObjUniquePtr = std::unique_ptr; + // Implementation of QSlotObjectBase for which the slot is a callable (function, PMF, functor, or lambda). // Args and R are the List of arguments and the return type of the signal to which the slot is connected. template