QHostInfoResult::postResultsReady: streamline the implementation
QHostInfo's lookup can notify a slot specified either via the string-based SLOT or via PMF/function objects. In the first case, an actual connection is established and a signal is emitted carrying the result object. In the PMF case, QHostInfo does not establish a connection and calls the slot object "directly" (using some private QObject APIs). The implementation was (and still somehow is) quite convoluted: the index of the QHostInfoResult signal to be emitted was looked up, and used to create a metacall event. However the metacall event was also intercepted in an override of event(), and from there the slot was called. But we don't need to look the signal index up at all to do that, since we are actually never emitting the signal! This can be done with a custom event. ... but I'm not doing that as that's reinventing the wheel. Instead, I'm using invokeMethod to call a private function of QHostInfoResult, and from there we can invoke the slot object. This allows us to get rid of the signal index lookup, remove the manual metacall event handling, and the copy() kludge for SlotObjUniquePtr. Change-Id: I2193acdad57788efd5250bd29f7a1c7505eed2f1 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>bb10
parent
797edbc58c
commit
5054279bee
|
|
@ -90,8 +90,8 @@ QHostInfoResult::~QHostInfoResult()
|
|||
the thread that made the call to lookupHost. That QHostInfoResult object
|
||||
then calls the user code in the correct thread.
|
||||
|
||||
The 'result' object deletes itself (via deleteLater) when the metacall
|
||||
event is received.
|
||||
The 'result' object deletes itself (via deleteLater) when
|
||||
finalizePostResultsReady is called.
|
||||
*/
|
||||
void QHostInfoResult::postResultsReady(const QHostInfo &info)
|
||||
{
|
||||
|
|
@ -104,43 +104,30 @@ void QHostInfoResult::postResultsReady(const QHostInfo &info)
|
|||
if (!receiver)
|
||||
return;
|
||||
|
||||
static const int signal_index = []() -> int {
|
||||
auto senderMetaObject = &QHostInfoResult::staticMetaObject;
|
||||
auto signal = &QHostInfoResult::resultsReady;
|
||||
int signal_index = -1;
|
||||
void *args[] = { &signal_index, &signal };
|
||||
senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
|
||||
return signal_index + QMetaObjectPrivate::signalOffset(senderMetaObject);
|
||||
}();
|
||||
|
||||
// a long-living version of this
|
||||
auto result = new QHostInfoResult(this);
|
||||
Q_CHECK_PTR(result);
|
||||
|
||||
auto metaCallEvent = QMetaCallEvent::create(std::move(slotObj), nullptr, signal_index, info);
|
||||
Q_CHECK_PTR(metaCallEvent);
|
||||
qApp->postEvent(result, metaCallEvent);
|
||||
QMetaObject::invokeMethod(result,
|
||||
&QHostInfoResult::finalizePostResultsReady,
|
||||
Qt::QueuedConnection,
|
||||
info);
|
||||
}
|
||||
|
||||
/*
|
||||
Receives the event posted by postResultsReady, and calls the functor.
|
||||
Receives the info from postResultsReady, and calls the functor.
|
||||
*/
|
||||
bool QHostInfoResult::event(QEvent *event)
|
||||
void QHostInfoResult::finalizePostResultsReady(const QHostInfo &info)
|
||||
{
|
||||
if (event->type() == QEvent::MetaCall) {
|
||||
Q_ASSERT(slotObj);
|
||||
Q_ASSERT(slotObj);
|
||||
|
||||
// we used to have a context object, but it's already destroyed
|
||||
if (receiver) {
|
||||
auto metaCallEvent = static_cast<QMetaCallEvent *>(event);
|
||||
auto args = metaCallEvent->args();
|
||||
slotObj->call(const_cast<QObject*>(receiver.data()), args);
|
||||
}
|
||||
|
||||
deleteLater();
|
||||
return true;
|
||||
// we used to have a context object, but it's already destroyed
|
||||
if (receiver) {
|
||||
void *args[] = { nullptr, const_cast<QHostInfo *>(&info) };
|
||||
slotObj->call(const_cast<QObject *>(receiver.data()), args);
|
||||
}
|
||||
return QObject::event(event);
|
||||
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -51,13 +51,13 @@ public:
|
|||
Q_SIGNALS:
|
||||
void resultsReady(const QHostInfo &info);
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
private Q_SLOTS:
|
||||
void finalizePostResultsReady(const QHostInfo &info);
|
||||
|
||||
private:
|
||||
QHostInfoResult(const QHostInfoResult *other)
|
||||
QHostInfoResult(QHostInfoResult *other)
|
||||
: receiver(other->receiver.get() != other ? other->receiver.get() : this),
|
||||
slotObj{copy(other->slotObj)}
|
||||
slotObj{std::move(other->slotObj)}
|
||||
{
|
||||
// cleanup if the application terminates before results are delivered
|
||||
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
|
||||
|
|
|
|||
Loading…
Reference in New Issue