QHostInfo: optimize container usage
Replace Java-style iterators with STL-style iterators. Java-style iterators have overhead. Use std::stable_partition with erase() instead of using remove() in a loop, with quadratic complexity. Introduce local template homebrew any_of (analog of std::any_of from C++11) to simplify current code. Also it's needed for following changes in this class. Change-Id: I2b11889ccc7630597c72aa20cdb266ae6ca2471a Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
This commit is contained in:
parent
a3def2869d
commit
447a508d00
@ -49,6 +49,8 @@
|
|||||||
#include <qurl.h>
|
#include <qurl.h>
|
||||||
#include <private/qnetworksession_p.h>
|
#include <private/qnetworksession_p.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
@ -59,6 +61,26 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager)
|
Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct ToBeLookedUpEquals {
|
||||||
|
typedef bool result_type;
|
||||||
|
explicit ToBeLookedUpEquals(const QString &toBeLookedUp) Q_DECL_NOTHROW : m_toBeLookedUp(toBeLookedUp) {}
|
||||||
|
result_type operator()(QHostInfoRunnable* lookup) const Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
return m_toBeLookedUp == lookup->toBeLookedUp;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
QString m_toBeLookedUp;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ### C++11: remove once we can use std::any_of()
|
||||||
|
template<class InputIt, class UnaryPredicate>
|
||||||
|
bool any_of(InputIt first, InputIt last, UnaryPredicate p)
|
||||||
|
{
|
||||||
|
return std::find_if(first, last, p) != last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QHostInfo
|
\class QHostInfo
|
||||||
\brief The QHostInfo class provides static functions for host name lookups.
|
\brief The QHostInfo class provides static functions for host name lookups.
|
||||||
@ -496,17 +518,17 @@ void QHostInfoRunnable::run()
|
|||||||
// now also iterate through the postponed ones
|
// now also iterate through the postponed ones
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&manager->mutex);
|
QMutexLocker locker(&manager->mutex);
|
||||||
QMutableListIterator<QHostInfoRunnable*> iterator(manager->postponedLookups);
|
const auto partitionBegin = std::stable_partition(manager->postponedLookups.rbegin(), manager->postponedLookups.rend(),
|
||||||
while (iterator.hasNext()) {
|
ToBeLookedUpEquals(toBeLookedUp)).base();
|
||||||
QHostInfoRunnable* postponed = iterator.next();
|
const auto partitionEnd = manager->postponedLookups.end();
|
||||||
if (toBeLookedUp == postponed->toBeLookedUp) {
|
for (auto it = partitionBegin; it != partitionEnd; ++it) {
|
||||||
// we can now emit
|
QHostInfoRunnable* postponed = *it;
|
||||||
iterator.remove();
|
// we can now emit
|
||||||
hostInfo.setLookupId(postponed->id);
|
hostInfo.setLookupId(postponed->id);
|
||||||
postponed->resultEmitter.emitResultsReady(hostInfo);
|
postponed->resultEmitter.emitResultsReady(hostInfo);
|
||||||
delete postponed;
|
delete postponed;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
manager->postponedLookups.erase(partitionBegin, partitionEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
manager->lookupFinished(this);
|
manager->lookupFinished(this);
|
||||||
@ -573,13 +595,7 @@ void QHostInfoLookupManager::work()
|
|||||||
QHostInfoRunnable* postponed = iterator.next();
|
QHostInfoRunnable* postponed = iterator.next();
|
||||||
|
|
||||||
// check if none of the postponed hostnames is currently running
|
// check if none of the postponed hostnames is currently running
|
||||||
bool alreadyRunning = false;
|
const bool alreadyRunning = any_of(currentLookups.cbegin(), currentLookups.cend(), ToBeLookedUpEquals(postponed->toBeLookedUp));
|
||||||
for (int i = 0; i < currentLookups.length(); i++) {
|
|
||||||
if (currentLookups.at(i)->toBeLookedUp == postponed->toBeLookedUp) {
|
|
||||||
alreadyRunning = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!alreadyRunning) {
|
if (!alreadyRunning) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
scheduledLookups.prepend(postponed); // prepend! we want to finish it ASAP
|
scheduledLookups.prepend(postponed); // prepend! we want to finish it ASAP
|
||||||
@ -594,13 +610,11 @@ void QHostInfoLookupManager::work()
|
|||||||
QHostInfoRunnable *scheduled = iterator.next();
|
QHostInfoRunnable *scheduled = iterator.next();
|
||||||
|
|
||||||
// check if a lookup for this host is already running, then postpone
|
// check if a lookup for this host is already running, then postpone
|
||||||
for (int i = 0; i < currentLookups.size(); i++) {
|
const bool alreadyRunning = any_of(currentLookups.cbegin(), currentLookups.cend(), ToBeLookedUpEquals(scheduled->toBeLookedUp));
|
||||||
if (currentLookups.at(i)->toBeLookedUp == scheduled->toBeLookedUp) {
|
if (alreadyRunning) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
postponedLookups.append(scheduled);
|
postponedLookups.append(scheduled);
|
||||||
scheduled = 0;
|
scheduled = 0;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scheduled && currentLookups.size() < threadPool.maxThreadCount()) {
|
if (scheduled && currentLookups.size() < threadPool.maxThreadCount()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user