summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-03-29 15:07:49 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-04-18 00:11:13 +0200
commitc4449c040c30a235c7871ec19b6ead413e8d094f (patch)
treef5f54a2512009e5bf0c3c81a8c1bef905278369b
parentdb7dc358978d93a246c020143ebcacf1fcf87217 (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.cpp24
-rw-r--r--src/corelib/kernel/qobject_p.h20
-rw-r--r--src/network/kernel/qhostinfo.cpp12
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);
}