diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index fa1db627e0..297d721d53 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2876,12 +2876,13 @@ Qt::PermissionStatus QCoreApplication::checkPermission(const QPermission &permis Called by the various requestPermission overloads to perform the request. - Calls the functor encapsulated in the \a slotObj in the given \a context + Calls the functor encapsulated in the \a slotObjRaw in the given \a context (which may be \c nullptr). */ void QCoreApplication::requestPermission(const QPermission &requestedPermission, - QtPrivate::QSlotObjectBase *slotObj, const QObject *context) + QtPrivate::QSlotObjectBase *slotObjRaw, const QObject *context) { + QtPrivate::SlotObjSharedPtr slotObj(QtPrivate::SlotObjUniquePtr{slotObjRaw}); // adopts if (QThread::currentThread() != QCoreApplicationPrivate::mainThread()) { qWarning(lcPermissions, "Permissions can only be requested from the GUI (main) thread"); return; @@ -2903,7 +2904,7 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, class PermissionReceiver : public QObject { public: - PermissionReceiver(QtPrivate::QSlotObjectBase *slotObject, const QObject *context) + explicit PermissionReceiver(const QtPrivate::SlotObjSharedPtr &slotObject, const QObject *context) : slotObject(slotObject), context(context) {} @@ -2916,7 +2917,6 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, // only execute if context object is still alive if (context) slotObject->call(const_cast(context.data()), metaCallEvent->args()); - slotObject->destroyIfLastRef(); deleteLater(); return true; @@ -2925,7 +2925,7 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, return QObject::event(event); } private: - QtPrivate::QSlotObjectBase *slotObject; + QtPrivate::SlotObjSharedPtr slotObject; QPointer context; }; PermissionReceiver *receiver = nullptr; @@ -2945,7 +2945,7 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, permission.m_status = status; if (receiver) { - auto metaCallEvent = QMetaCallEvent::create(slotObj, qApp, + auto metaCallEvent = QMetaCallEvent::create(slotObj.get(), qApp, PermissionReceivedID, permission); qApp->postEvent(receiver, metaCallEvent); } else { @@ -2953,9 +2953,6 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, slotObj->call(const_cast(context), argv); } } - - if (!receiver) - slotObj->destroyIfLastRef(); }); } diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index d8961925ed..68da6e04e7 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -453,6 +453,39 @@ namespace QtPrivate { using SlotObjUniquePtr = std::unique_ptr; + class SlotObjSharedPtr { + SlotObjUniquePtr obj; + public: + Q_NODISCARD_CTOR Q_IMPLICIT SlotObjSharedPtr() noexcept = default; + Q_NODISCARD_CTOR Q_IMPLICIT SlotObjSharedPtr(std::nullptr_t) noexcept : SlotObjSharedPtr() {} + Q_NODISCARD_CTOR explicit SlotObjSharedPtr(SlotObjUniquePtr o) + : obj(std::move(o)) + { + // does NOT ref() (takes unique_ptr by value) + // (that's why (QSlotObjectBase*) ctor doesn't exisit: don't know whether that one _should_) + } + Q_NODISCARD_CTOR SlotObjSharedPtr(const SlotObjSharedPtr &other) noexcept + : obj(other.obj.get()) + { + if (obj) + obj->ref(); + } + SlotObjSharedPtr &operator=(const SlotObjSharedPtr &other) noexcept + { auto copy = other; swap(copy); return *this; } + + Q_NODISCARD_CTOR SlotObjSharedPtr(SlotObjSharedPtr &&other) noexcept = default; + SlotObjSharedPtr &operator=(SlotObjSharedPtr &&other) noexcept = default; + ~SlotObjSharedPtr() = default; + + void swap(SlotObjSharedPtr &other) noexcept { obj.swap(other.obj); } + + auto get() const noexcept { return obj.get(); } + auto operator->() const noexcept { return get(); } + + explicit operator bool() const noexcept { return bool(obj); } + }; + + // 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