diff options
Diffstat (limited to 'src/network/kernel/qhostinfo.cpp')
-rw-r--r-- | src/network/kernel/qhostinfo.cpp | 128 |
1 files changed, 68 insertions, 60 deletions
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 6a6519e9c1..62bb210ca1 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -72,6 +72,16 @@ Q_APPLICATION_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) } +QHostInfoResult::QHostInfoResult(const QObject *receiver, QtPrivate::SlotObjUniquePtr slot) + : receiver{receiver ? receiver : this}, slotObj{std::move(slot)} +{ + Q_ASSERT(this->receiver); + moveToThread(this->receiver->thread()); +} + +QHostInfoResult::~QHostInfoResult() + = default; + /* The calling thread is likely the one that executes the lookup via QHostInfoRunnable. Unless we operate with a queued connection already, @@ -80,8 +90,8 @@ Q_APPLICATION_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) 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) { @@ -91,55 +101,33 @@ void QHostInfoResult::postResultsReady(const QHostInfo &info) return; } // we used to have a context object, but it's already destroyed - if (withContextObject && !receiver) + 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); - const int nargs = 2; - auto metaCallEvent = new QMetaCallEvent(slotObj, nullptr, signal_index, nargs); - 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); + 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); - auto metaCallEvent = static_cast<QMetaCallEvent *>(event); - auto args = metaCallEvent->args(); - // we didn't have a context object, or it's still alive - if (!withContextObject || receiver) - slotObj->call(const_cast<QObject*>(receiver.data()), args); - slotObj->destroyIfLastRef(); - - deleteLater(); - return true; + Q_ASSERT(slotObj); + + // 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(); } /*! @@ -202,7 +190,7 @@ bool QHostInfoResult::event(QEvent *event) static int nextId() { - static QBasicAtomicInt counter = Q_BASIC_ATOMIC_INITIALIZER(0); + Q_CONSTINIT static QBasicAtomicInt counter = Q_BASIC_ATOMIC_INITIALIZER(0); return 1 + counter.fetchAndAddRelaxed(1); } @@ -233,10 +221,17 @@ static int nextId() \note There is no guarantee on the order the signals will be emitted if you start multiple requests with lookupHost(). + \note In Qt versions prior to 6.7, this function took \a receiver as + (non-const) \c{QObject*}. + \sa abortHostLookup(), addresses(), error(), fromName() */ -int QHostInfo::lookupHost(const QString &name, QObject *receiver, const char *member) +int QHostInfo::lookupHost(const QString &name, const QObject *receiver, const char *member) { + if (!receiver || !member) { + qWarning("QHostInfo::lookupHost: both the receiver and the member to invoke must be non-null"); + return -1; + } return QHostInfo::lookupHostImpl(name, receiver, nullptr, member); } @@ -262,7 +257,7 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, const char *me */ /*! - \fn template<typename Functor> int QHostInfo::lookupHost(const QString &name, Functor functor) + \fn template<typename Functor> int QHostInfo::lookupHost(const QString &name, Functor &&functor) \since 5.9 @@ -734,22 +729,25 @@ QString QHostInfo::localHostName() \internal Called by the various lookupHost overloads to perform the lookup. - Signals either the functor encapuslated in the \a slotObj in the context + Signals either the functor encapuslated in the \a slotObjRaw in the context of \a receiver, or the \a member slot of the \a receiver. - \a receiver might be the nullptr, but only if a \a slotObj is provided. + \a receiver might be the nullptr, but only if a \a slotObjRaw is provided. */ int QHostInfo::lookupHostImpl(const QString &name, const QObject *receiver, - QtPrivate::QSlotObjectBase *slotObj, + QtPrivate::QSlotObjectBase *slotObjRaw, const char *member) { + QtPrivate::SlotObjUniquePtr slotObj{slotObjRaw}; #if defined QHOSTINFO_DEBUG qDebug("QHostInfo::lookupHostImpl(\"%s\", %p, %p, %s)", - name.toLatin1().constData(), receiver, slotObj, member ? member + 1 : 0); + name.toLatin1().constData(), receiver, slotObj.get(), member ? member + 1 : 0); #endif Q_ASSERT(!member != !slotObj); // one of these must be set, but not both Q_ASSERT(receiver || slotObj); + Q_ASSERT(!member || receiver); // if member is set, also is receiver + const bool isUsingStringBasedSlot = static_cast<bool>(member); if (!QAbstractEventDispatcher::instance(QThread::currentThread())) { qWarning("QHostInfo::lookupHost() called with no event dispatcher"); @@ -765,10 +763,11 @@ int QHostInfo::lookupHostImpl(const QString &name, hostInfo.setError(QHostInfo::HostNotFound); hostInfo.setErrorString(QCoreApplication::translate("QHostInfo", "No host name given")); - QHostInfoResult result(receiver, slotObj); - if (receiver && member) + QHostInfoResult result(receiver, std::move(slotObj)); + if (isUsingStringBasedSlot) { QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + } result.postResultsReady(hostInfo); return id; @@ -782,10 +781,11 @@ int QHostInfo::lookupHostImpl(const QString &name, QHostInfo hostInfo = QHostInfoAgent::lookup(name); hostInfo.setLookupId(id); - QHostInfoResult result(receiver, slotObj); - if (receiver && member) + QHostInfoResult result(receiver, std::move(slotObj)); + if (isUsingStringBasedSlot) { QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + } result.postResultsReady(hostInfo); #else QHostInfoLookupManager *manager = theHostInfoLookupManager(); @@ -798,20 +798,22 @@ int QHostInfo::lookupHostImpl(const QString &name, QHostInfo info = manager->cache.get(name, &valid); if (valid) { info.setLookupId(id); - QHostInfoResult result(receiver, slotObj); - if (receiver && member) + QHostInfoResult result(receiver, std::move(slotObj)); + if (isUsingStringBasedSlot) { QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + } result.postResultsReady(info); return id; } } // cache is not enabled or it was not in the cache, do normal lookup - QHostInfoRunnable *runnable = new QHostInfoRunnable(name, id, receiver, slotObj); - if (receiver && member) + QHostInfoRunnable *runnable = new QHostInfoRunnable(name, id, receiver, std::move(slotObj)); + if (isUsingStringBasedSlot) { QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + } manager->scheduleLookup(runnable); } #endif // Q_OS_WASM @@ -819,12 +821,15 @@ int QHostInfo::lookupHostImpl(const QString &name, } QHostInfoRunnable::QHostInfoRunnable(const QString &hn, int i, const QObject *receiver, - QtPrivate::QSlotObjectBase *slotObj) : - toBeLookedUp(hn), id(i), resultEmitter(receiver, slotObj) + QtPrivate::SlotObjUniquePtr slotObj) + : toBeLookedUp{hn}, id{i}, resultEmitter{receiver, std::move(slotObj)} { setAutoDelete(true); } +QHostInfoRunnable::~QHostInfoRunnable() + = default; + // the QHostInfoLookupManager will at some point call this via a QThreadPool void QHostInfoRunnable::run() { @@ -934,7 +939,7 @@ void QHostInfoLookupManager::rescheduleWithMutexHeld() if (!finishedLookups.isEmpty()) { // remove ID from aborted if it is in there - for (int i = 0; i < finishedLookups.length(); i++) { + for (int i = 0; i < finishedLookups.size(); i++) { abortedLookups.removeAll(finishedLookups.at(i)->id); } @@ -962,7 +967,7 @@ void QHostInfoLookupManager::rescheduleWithMutexHeld() isAlreadyRunning).second, scheduledLookups.end()); - const int availableThreads = threadPool.maxThreadCount() - currentLookups.size(); + const int availableThreads = std::max(threadPool.maxThreadCount(), 1) - currentLookups.size(); if (availableThreads > 0) { int readyToStartCount = qMin(availableThreads, scheduledLookups.size()); auto it = scheduledLookups.begin(); @@ -1000,9 +1005,12 @@ void QHostInfoLookupManager::abortLookup(int id) if (wasDeleted) return; + if (id == -1) + return; + #if QT_CONFIG(thread) // is postponed? delete and return - for (int i = 0; i < postponedLookups.length(); i++) { + for (int i = 0; i < postponedLookups.size(); i++) { if (postponedLookups.at(i)->id == id) { delete postponedLookups.takeAt(i); return; @@ -1011,7 +1019,7 @@ void QHostInfoLookupManager::abortLookup(int id) #endif // is scheduled? delete and return - for (int i = 0; i < scheduledLookups.length(); i++) { + for (int i = 0; i < scheduledLookups.size(); i++) { if (scheduledLookups.at(i)->id == id) { delete scheduledLookups.takeAt(i); return; |