QNetworkAcesssCache: replace a QQueue with a std::vector

The code didn't really use the queue as a queue, because it enqueued
one at a time, but dequeued potentially many. Even if it actually
decays to actual queue behavior: for the small number of elements
expected, a vector would still be preferable over the per-element
allocation performed by QQueue.

Because std::vector doesn't have pop_front(), I took the liberty of
making the dequeue code easier to read by using find_if with an
aptly-named lambda.

Change-Id: I09bd7ede50cb8ab5af5d1fc2ede37a3731f67070
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Marc Mutz 2019-05-13 20:12:23 +02:00
parent 041a5ff076
commit 84536ae61e

View File

@ -40,11 +40,12 @@
#include "qnetworkaccesscache_p.h"
#include "QtCore/qpointer.h"
#include "QtCore/qdatetime.h"
#include "QtCore/qqueue.h"
#include "qnetworkaccessmanager_p.h"
#include "qnetworkreply_p.h"
#include "qnetworkrequest.h"
#include <vector>
QT_BEGIN_NAMESPACE
enum ExpiryTimeEnum {
@ -63,7 +64,7 @@ namespace {
struct QNetworkAccessCache::Node
{
QDateTime timestamp;
QQueue<Receiver> receiverQueue;
std::vector<Receiver> receiverQueue;
QByteArray key;
Node *older, *newer;
@ -277,10 +278,7 @@ bool QNetworkAccessCache::requestEntry(const QByteArray &key, QObject *target, c
// object is not shareable and is in use
// queue for later use
Q_ASSERT(node->older == 0 && node->newer == 0);
Receiver receiver;
receiver.object = target;
receiver.member = member;
node->receiverQueue.enqueue(receiver);
node->receiverQueue.push_back({target, member});
// request queued
return true;
@ -331,17 +329,19 @@ void QNetworkAccessCache::releaseEntry(const QByteArray &key)
Q_ASSERT(node->useCount > 0);
// are there other objects waiting?
if (!node->receiverQueue.isEmpty()) {
// queue another activation
Receiver receiver;
do {
receiver = node->receiverQueue.dequeue();
} while (receiver.object.isNull() && !node->receiverQueue.isEmpty());
const auto objectStillExists = [](const Receiver &r) { return !r.object.isNull(); };
if (!receiver.object.isNull()) {
emitEntryReady(node, receiver.object, receiver.member);
return;
}
auto &queue = node->receiverQueue;
auto qit = std::find_if(queue.begin(), queue.end(), objectStillExists);
const Receiver receiver = qit == queue.end() ? Receiver{} : std::move(*qit++) ;
queue.erase(queue.begin(), qit);
if (receiver.object) {
// queue another activation
emitEntryReady(node, receiver.object, receiver.member);
return;
}
if (!--node->useCount) {