diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2023-03-29 15:07:49 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2023-04-18 00:11:13 +0200 |
commit | c4449c040c30a235c7871ec19b6ead413e8d094f (patch) | |
tree | f5f54a2512009e5bf0c3c81a8c1bef905278369b | |
parent | db7dc358978d93a246c020143ebcacf1fcf87217 (diff) |
Add helper template for metacall event creation
Setting up the args and types arrays is cumbersome and error prone, and
we do it at least twice in qtbase. Provide a central implementation as a
variadic template function, and make it exception-safe with a unique_ptr
(the destructor of QMetaCallEvent will destroy the cloned arguments).
Change-Id: I5ff400467928446264eaedddb394691e9e23d22e
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 24 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 20 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo.cpp | 12 |
3 files changed, 32 insertions, 24 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 7c238af700..064a323507 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2850,6 +2850,13 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, Q_ASSERT(slotObj); + // Used as the signalID in the metacall event and only used to + // verify that we are not processing an unrelated event, not to + // emit the right signal. So using a value that can never clash + // with any signal index. Clang doesn't like this to be a static + // member of the PermissionReceiver. + static constexpr ushort PermissionReceivedID = 0xffff; + // If we have a context object, then we dispatch the permission response // asynchronously through a received object that lives in the same thread // as the context object. Otherwise we call the functor synchronously when @@ -2860,11 +2867,12 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, PermissionReceiver(QtPrivate::QSlotObjectBase *slotObject, const QObject *context) : slotObject(slotObject), context(context) {} + protected: bool event(QEvent *event) override { if (event->type() == QEvent::MetaCall) { auto metaCallEvent = static_cast<QMetaCallEvent *>(event); - if (metaCallEvent->id() == ushort(-1)) { + if (metaCallEvent->id() == PermissionReceivedID) { Q_ASSERT(slotObject); // only execute if context object is still alive if (context) @@ -2898,18 +2906,8 @@ void QCoreApplication::requestPermission(const QPermission &requestedPermission, permission.m_status = status; if (receiver) { - const int nargs = 2; - auto metaCallEvent = new QMetaCallEvent(slotObj, qApp, ushort(-1), nargs); - Q_CHECK_PTR(metaCallEvent); - void **args = metaCallEvent->args(); - QMetaType *types = metaCallEvent->types(); - const auto voidType = QMetaType::fromType<void>(); - const auto permissionType = QMetaType::fromType<QPermission>(); - types[0] = voidType; - types[1] = permissionType; - args[0] = nullptr; - args[1] = permissionType.create(&permission); - Q_CHECK_PTR(args[1]); + auto metaCallEvent = QMetaCallEvent::create(slotObj, qApp, + PermissionReceivedID, permission); qApp->postEvent(receiver, metaCallEvent); } else { void *argv[] = { nullptr, &permission }; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index f9bb93f960..d56e9aa60c 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -402,6 +402,26 @@ public: ~QMetaCallEvent() override; + template<typename ...Args> + static QMetaCallEvent *create(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, + int signal_index, Args ...argv) + { + auto metaCallEvent = std::make_unique<QMetaCallEvent>(slotObj, sender, + signal_index, int(1 + sizeof...(Args))); + + void **args = metaCallEvent->args(); + QMetaType *types = metaCallEvent->types(); + const std::array<void *, sizeof...(Args) + 1> argp{ nullptr, std::addressof(argv)... }; + const std::array metaTypes{ QMetaType::fromType<void>(), QMetaType::fromType<Args>()... }; + for (size_t i = 0; i < sizeof...(Args) + 1; ++i) { + types[i] = metaTypes[i]; + args[i] = types[i].create(argp[i]); + Q_CHECK_PTR(!i || args[i]); + } + + return metaCallEvent.release(); + } + inline int id() const { return d.method_offset_ + d.method_relative_; } inline const void * const* args() const { return d.args_; } inline void ** args() { return d.args_; } diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 2283766b97..1631e97652 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -107,18 +107,8 @@ void QHostInfoResult::postResultsReady(const QHostInfo &info) auto result = new QHostInfoResult(this); Q_CHECK_PTR(result); - const int nargs = 2; - auto metaCallEvent = new QMetaCallEvent(slotObj, nullptr, signal_index, nargs); + auto metaCallEvent = QMetaCallEvent::create(slotObj, nullptr, signal_index, info); Q_CHECK_PTR(metaCallEvent); - void **args = metaCallEvent->args(); - QMetaType *types = metaCallEvent->types(); - auto voidType = QMetaType::fromType<void>(); - auto hostInfoType = QMetaType::fromType<QHostInfo>(); - types[0] = voidType; - types[1] = hostInfoType; - args[0] = nullptr; - args[1] = hostInfoType.create(&info); - Q_CHECK_PTR(args[1]); qApp->postEvent(result, metaCallEvent); } |