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>
This commit is contained in:
parent
db7dc35897
commit
c4449c040c
@ -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 };
|
||||
|
@ -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_; }
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user