From 34ddddae1b8449c90911fb74288c72f728c5a392 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 10 Mar 2014 12:06:07 -0700 Subject: [PATCH] Basic LRU cache. Closes #2234. --- interface/src/renderer/GeometryCache.h | 2 +- interface/src/renderer/TextureCache.cpp | 2 +- libraries/shared/src/ResourceCache.cpp | 25 +++++++++++++++++-------- libraries/shared/src/ResourceCache.h | 10 +++++++++- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 6e9604e79e..da1955039d 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -89,7 +89,7 @@ public: protected: virtual void downloadFinished(QNetworkReply* reply); - virtual void reinsert() const; + virtual void reinsert(); Q_INVOKABLE void setGeometry(const FBXGeometry& geometry); diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index e3f750e676..80eef66ff5 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -133,7 +133,7 @@ QSharedPointer TextureCache::getTexture(const QUrl& url, bool no texture->setCache(this); _dilatableNetworkTextures.insert(url, texture); } else { - _unusedResources.removeOne(texture); + _unusedResources.remove(texture->getLRUKey()); } return texture; } diff --git a/libraries/shared/src/ResourceCache.cpp b/libraries/shared/src/ResourceCache.cpp index 6434376cd8..65c68b23ef 100644 --- a/libraries/shared/src/ResourceCache.cpp +++ b/libraries/shared/src/ResourceCache.cpp @@ -15,7 +15,8 @@ #include "ResourceCache.h" ResourceCache::ResourceCache(QObject* parent) : - QObject(parent) { + QObject(parent), + _lastLRUKey(0) { } ResourceCache::~ResourceCache() { @@ -38,19 +39,21 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& _resources.insert(url, resource); } else { - _unusedResources.removeOne(resource); + _unusedResources.remove(resource->getLRUKey()); } return resource; } void ResourceCache::addUnusedResource(const QSharedPointer& resource) { - const int RETAINED_RESOURCE_COUNT = 1; + const int RETAINED_RESOURCE_COUNT = 50; if (_unusedResources.size() > RETAINED_RESOURCE_COUNT) { // unload the oldest resource - QSharedPointer oldResource = _unusedResources.takeFirst(); - oldResource->setCache(NULL); + QMap >::iterator it = _unusedResources.begin(); + it.value()->setCache(NULL); + _unusedResources.erase(it); } - _unusedResources.append(resource); + resource->setLRUKey(++_lastLRUKey); + _unusedResources.insert(resource->getLRUKey(), resource); } void ResourceCache::attemptRequest(Resource* resource) { @@ -100,6 +103,7 @@ Resource::Resource(const QUrl& url, bool delayLoad) : _startedLoading(false), _failedToLoad(false), _loaded(false), + _lruKey(0), _reply(NULL), _attempts(0) { @@ -171,10 +175,9 @@ void Resource::allReferencesCleared() { reinsert(); // add to the unused list - _cache->_unusedResources.append(self); + _cache->addUnusedResource(self); } else { - qDebug() << "deleting" << _url; delete this; } } @@ -231,6 +234,7 @@ void Resource::makeRequest() { connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64))); connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError())); + connect(_reply, SIGNAL(finished()), SLOT(handleReplyFinished())); _replyTimer = new QTimer(this); connect(_replyTimer, SIGNAL(timeout()), SLOT(handleReplyTimeout())); @@ -275,6 +279,11 @@ void Resource::handleReplyError(QNetworkReply::NetworkError error, QDebug debug) } } +void Resource::handleReplyFinished() { + qDebug() << "Got finished without download progress/error?" << _url; + handleDownloadProgress(0, 0); +} + uint qHash(const QPointer& value, uint seed) { return qHash(value.data(), seed); } diff --git a/libraries/shared/src/ResourceCache.h b/libraries/shared/src/ResourceCache.h index 2826902598..a544f43731 100644 --- a/libraries/shared/src/ResourceCache.h +++ b/libraries/shared/src/ResourceCache.h @@ -42,7 +42,7 @@ public: protected: - QList > _unusedResources; + QMap > _unusedResources; /// Loads a resource from the specified URL. /// \param fallback a fallback URL to load if the desired one is unavailable @@ -65,6 +65,7 @@ private: friend class Resource; QHash > _resources; + int _lastLRUKey; static QNetworkAccessManager* _networkAccessManager; static int _requestLimit; @@ -80,6 +81,9 @@ public: Resource(const QUrl& url, bool delayLoad = false); ~Resource(); + /// Returns the key last used to identify this resource in the unused map. + int getLRUKey() const { return _lruKey; } + /// Makes sure that the resource has started loading. void ensureLoading(); @@ -132,16 +136,20 @@ private slots: void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal); void handleReplyError(); + void handleReplyFinished(); void handleReplyTimeout(); private: + void setLRUKey(int lruKey) { _lruKey = lruKey; } + void makeRequest(); void handleReplyError(QNetworkReply::NetworkError error, QDebug debug); friend class ResourceCache; + int _lruKey; QNetworkReply* _reply; QTimer* _replyTimer; qint64 _bytesReceived;