Merge pull request #14139 from SamGondelman/animation

Fix various ResourceCache bugs
This commit is contained in:
John Conklin II 2018-10-17 11:13:35 -07:00 committed by GitHub
commit e59e3720fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 119 additions and 134 deletions

View file

@ -152,6 +152,8 @@
#include <avatars-renderer/ScriptAvatar.h> #include <avatars-renderer/ScriptAvatar.h>
#include <RenderableEntityItem.h> #include <RenderableEntityItem.h>
#include <procedural/ProceduralSkybox.h> #include <procedural/ProceduralSkybox.h>
#include <model-networking/MaterialCache.h>
#include "recording/ClipCache.h"
#include "AudioClient.h" #include "AudioClient.h"
#include "audio/AudioScope.h" #include "audio/AudioScope.h"
@ -328,9 +330,9 @@ static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains
#endif #endif
#if !defined(Q_OS_ANDROID) #if !defined(Q_OS_ANDROID)
static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16; static const uint32_t MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16;
#else #else
static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 4; static const uint32_t MAX_CONCURRENT_RESOURCE_DOWNLOADS = 4;
#endif #endif
// For processing on QThreadPool, we target a number of threads after reserving some // For processing on QThreadPool, we target a number of threads after reserving some
@ -1327,7 +1329,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads"); QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads");
bool success; bool success;
int concurrentDownloads = concurrentDownloadsStr.toInt(&success); uint32_t concurrentDownloads = concurrentDownloadsStr.toUInt(&success);
if (!success) { if (!success) {
concurrentDownloads = MAX_CONCURRENT_RESOURCE_DOWNLOADS; concurrentDownloads = MAX_CONCURRENT_RESOURCE_DOWNLOADS;
} }
@ -2054,7 +2056,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
} }
properties["active_downloads"] = loadingRequests.size(); properties["active_downloads"] = loadingRequests.size();
properties["pending_downloads"] = ResourceCache::getPendingRequestCount(); properties["pending_downloads"] = (int)ResourceCache::getPendingRequestCount();
properties["active_downloads_details"] = loadingRequestsStats; properties["active_downloads_details"] = loadingRequestsStats;
auto statTracker = DependencyManager::get<StatTracker>(); auto statTracker = DependencyManager::get<StatTracker>();
@ -4653,8 +4655,8 @@ void Application::idle() {
PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate()); PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate());
} }
PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, _renderLoopCounter.rate()); PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, _renderLoopCounter.rate());
PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", int, ResourceCache::getLoadingRequests().length()); PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", uint32_t, ResourceCache::getLoadingRequestCount());
PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", int, ResourceCache::getPendingRequestCount()); PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", uint32_t, ResourceCache::getPendingRequestCount());
PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get<StatTracker>()->getStat("Processing").toInt()); PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get<StatTracker>()->getStat("Processing").toInt());
PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt()); PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt());
auto renderConfig = _renderEngine->getConfiguration(); auto renderConfig = _renderEngine->getConfiguration();
@ -5399,13 +5401,21 @@ void Application::reloadResourceCaches() {
queryOctree(NodeType::EntityServer, PacketType::EntityQuery); queryOctree(NodeType::EntityServer, PacketType::EntityQuery);
// Clear the entities and their renderables
getEntities()->clear();
DependencyManager::get<AssetClient>()->clearCache(); DependencyManager::get<AssetClient>()->clearCache();
DependencyManager::get<ScriptCache>()->clearCache(); DependencyManager::get<ScriptCache>()->clearCache();
// Clear all the resource caches
DependencyManager::get<ResourceCacheSharedItems>()->clear();
DependencyManager::get<AnimationCache>()->refreshAll(); DependencyManager::get<AnimationCache>()->refreshAll();
DependencyManager::get<ModelCache>()->refreshAll();
DependencyManager::get<SoundCache>()->refreshAll(); DependencyManager::get<SoundCache>()->refreshAll();
MaterialCache::instance().refreshAll();
DependencyManager::get<ModelCache>()->refreshAll();
ShaderCache::instance().refreshAll();
DependencyManager::get<TextureCache>()->refreshAll(); DependencyManager::get<TextureCache>()->refreshAll();
DependencyManager::get<recording::ClipCache>()->refreshAll();
DependencyManager::get<NodeList>()->reset(); // Force redownload of .fst models DependencyManager::get<NodeList>()->reset(); // Force redownload of .fst models
@ -6470,9 +6480,12 @@ void Application::clearDomainOctreeDetails() {
skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_DEFAULT); skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_DEFAULT);
DependencyManager::get<AnimationCache>()->clearUnusedResources(); DependencyManager::get<AnimationCache>()->clearUnusedResources();
DependencyManager::get<ModelCache>()->clearUnusedResources();
DependencyManager::get<SoundCache>()->clearUnusedResources(); DependencyManager::get<SoundCache>()->clearUnusedResources();
MaterialCache::instance().clearUnusedResources();
DependencyManager::get<ModelCache>()->clearUnusedResources();
ShaderCache::instance().clearUnusedResources();
DependencyManager::get<TextureCache>()->clearUnusedResources(); DependencyManager::get<TextureCache>()->clearUnusedResources();
DependencyManager::get<recording::ClipCache>()->clearUnusedResources();
getMyAvatar()->setAvatarEntityDataChanged(true); getMyAvatar()->setAvatarEntityDataChanged(true);
} }

View file

@ -267,8 +267,8 @@ void Stats::updateStats(bool force) {
auto loadingRequests = ResourceCache::getLoadingRequests(); auto loadingRequests = ResourceCache::getLoadingRequests();
STAT_UPDATE(downloads, loadingRequests.size()); STAT_UPDATE(downloads, loadingRequests.size());
STAT_UPDATE(downloadLimit, ResourceCache::getRequestLimit()) STAT_UPDATE(downloadLimit, (int)ResourceCache::getRequestLimit())
STAT_UPDATE(downloadsPending, ResourceCache::getPendingRequestCount()); STAT_UPDATE(downloadsPending, (int)ResourceCache::getPendingRequestCount());
STAT_UPDATE(processing, DependencyManager::get<StatTracker>()->getStat("Processing").toInt()); STAT_UPDATE(processing, DependencyManager::get<StatTracker>()->getStat("Processing").toInt());
STAT_UPDATE(processingPending, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt()); STAT_UPDATE(processingPending, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt());

View file

@ -32,12 +32,6 @@ AnimationCache::AnimationCache(QObject* parent) :
} }
AnimationPointer AnimationCache::getAnimation(const QUrl& url) { AnimationPointer AnimationCache::getAnimation(const QUrl& url) {
if (QThread::currentThread() != thread()) {
AnimationPointer result;
BLOCKING_INVOKE_METHOD(this, "getAnimation",
Q_RETURN_ARG(AnimationPointer, result), Q_ARG(const QUrl&, url));
return result;
}
return getResource(url).staticCast<Animation>(); return getResource(url).staticCast<Animation>();
} }

View file

@ -30,12 +30,6 @@ SoundCache::SoundCache(QObject* parent) :
} }
SharedSoundPointer SoundCache::getSound(const QUrl& url) { SharedSoundPointer SoundCache::getSound(const QUrl& url) {
if (QThread::currentThread() != thread()) {
SharedSoundPointer result;
BLOCKING_INVOKE_METHOD(this, "getSound",
Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url));
return result;
}
return getResource(url).staticCast<Sound>(); return getResource(url).staticCast<Sound>();
} }

View file

@ -75,8 +75,6 @@ protected:
void makeLocalRequest(); void makeLocalRequest();
Q_INVOKABLE void handleLocalRequestCompleted(); Q_INVOKABLE void handleLocalRequestCompleted();
virtual bool isCacheable() const override { return _loaded; }
Q_INVOKABLE virtual void downloadFinished(const QByteArray& data) override; Q_INVOKABLE virtual void downloadFinished(const QByteArray& data) override;
bool handleFailedRequest(ResourceRequest::Result result) override; bool handleFailedRequest(ResourceRequest::Result result) override;

View file

@ -27,28 +27,35 @@
#include "NetworkLogging.h" #include "NetworkLogging.h"
#include "NodeList.h" #include "NodeList.h"
bool ResourceCacheSharedItems::appendRequest(QWeakPointer<Resource> resource) {
#define clamp(x, min, max) (((x) < (min)) ? (min) :\
(((x) > (max)) ? (max) :\
(x)))
void ResourceCacheSharedItems::appendActiveRequest(QWeakPointer<Resource> resource) {
Lock lock(_mutex); Lock lock(_mutex);
_loadingRequests.append(resource); if ((uint32_t)_loadingRequests.size() < _requestLimit) {
_loadingRequests.append(resource);
return true;
} else {
_pendingRequests.append(resource);
return false;
}
} }
void ResourceCacheSharedItems::appendPendingRequest(QWeakPointer<Resource> resource) { void ResourceCacheSharedItems::setRequestLimit(uint32_t limit) {
Lock lock(_mutex); Lock lock(_mutex);
_pendingRequests.append(resource); _requestLimit = limit;
} }
QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getPendingRequests() { uint32_t ResourceCacheSharedItems::getRequestLimit() const {
Lock lock(_mutex);
return _requestLimit;
}
QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getPendingRequests() const {
QList<QSharedPointer<Resource>> result; QList<QSharedPointer<Resource>> result;
Lock lock(_mutex); Lock lock(_mutex);
foreach(QSharedPointer<Resource> resource, _pendingRequests) { foreach (QWeakPointer<Resource> resource, _pendingRequests) {
if (resource) { auto locked = resource.lock();
result.append(resource); if (locked) {
result.append(locked);
} }
} }
@ -60,16 +67,12 @@ uint32_t ResourceCacheSharedItems::getPendingRequestsCount() const {
return _pendingRequests.size(); return _pendingRequests.size();
} }
QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getLoadingRequests() { QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getLoadingRequests() const {
QList<QSharedPointer<Resource>> result; QList<QSharedPointer<Resource>> result;
Lock lock(_mutex); {
Lock lock(_mutex);
foreach(QSharedPointer<Resource> resource, _loadingRequests) { result = _loadingRequests;
if (resource) {
result.append(resource);
}
} }
return result; return result;
} }
@ -131,6 +134,11 @@ QSharedPointer<Resource> ResourceCacheSharedItems::getHighestPendingRequest() {
return highestResource; return highestResource;
} }
void ResourceCacheSharedItems::clear() {
Lock lock(_mutex);
_pendingRequests.clear();
_loadingRequests.clear();
}
ScriptableResourceCache::ScriptableResourceCache(QSharedPointer<ResourceCache> resourceCache) { ScriptableResourceCache::ScriptableResourceCache(QSharedPointer<ResourceCache> resourceCache) {
_resourceCache = resourceCache; _resourceCache = resourceCache;
@ -244,9 +252,7 @@ ResourceCache::ResourceCache(QObject* parent) : QObject(parent) {
} }
} }
ResourceCache::~ResourceCache() { ResourceCache::~ResourceCache() {}
clearUnusedResources();
}
void ResourceCache::clearATPAssets() { void ResourceCache::clearATPAssets() {
{ {
@ -260,6 +266,7 @@ void ResourceCache::clearATPAssets() {
if (auto strongRef = resource.lock()) { if (auto strongRef = resource.lock()) {
// Make sure the resource won't reinsert itself // Make sure the resource won't reinsert itself
strongRef->setCache(nullptr); strongRef->setCache(nullptr);
_totalResourcesSize -= strongRef->getBytes();
} }
} }
} }
@ -269,28 +276,18 @@ void ResourceCache::clearATPAssets() {
for (auto& resource : _unusedResources.values()) { for (auto& resource : _unusedResources.values()) {
if (resource->getURL().scheme() == URL_SCHEME_ATP) { if (resource->getURL().scheme() == URL_SCHEME_ATP) {
_unusedResources.remove(resource->getLRUKey()); _unusedResources.remove(resource->getLRUKey());
} _unusedResourcesSize -= resource->getBytes();
}
}
{
QWriteLocker locker(&_resourcesToBeGottenLock);
auto it = _resourcesToBeGotten.begin();
while (it != _resourcesToBeGotten.end()) {
if (it->scheme() == URL_SCHEME_ATP) {
it = _resourcesToBeGotten.erase(it);
} else {
++it;
} }
} }
} }
resetResourceCounters();
} }
void ResourceCache::refreshAll() { void ResourceCache::refreshAll() {
// Clear all unused resources so we don't have to reload them // Clear all unused resources so we don't have to reload them
clearUnusedResources(); clearUnusedResources();
resetResourceCounters(); resetUnusedResourceCounter();
QHash<QUrl, QWeakPointer<Resource>> resources; QHash<QUrl, QWeakPointer<Resource>> resources;
{ {
@ -306,21 +303,6 @@ void ResourceCache::refreshAll() {
} }
} }
void ResourceCache::refresh(const QUrl& url) {
QSharedPointer<Resource> resource;
{
QReadLocker locker(&_resourcesLock);
resource = _resources.value(url).lock();
}
if (resource) {
resource->refresh();
} else {
removeResource(url);
resetResourceCounters();
}
}
QVariantList ResourceCache::getResourceList() { QVariantList ResourceCache::getResourceList() {
QVariantList list; QVariantList list;
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
@ -338,12 +320,13 @@ QVariantList ResourceCache::getResourceList() {
return list; return list;
} }
void ResourceCache::setRequestLimit(int limit) { void ResourceCache::setRequestLimit(uint32_t limit) {
_requestLimit = limit; auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
sharedItems->setRequestLimit(limit);
// Now go fill any new request spots // Now go fill any new request spots
while (attemptHighestPriorityRequest()) { while (sharedItems->getLoadingRequestsCount() < limit && sharedItems->getPendingRequestsCount() > 0) {
// just keep looping until we reach the new limit or no more pending requests attemptHighestPriorityRequest();
} }
} }
@ -381,9 +364,9 @@ QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl&
} }
void ResourceCache::setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize) { void ResourceCache::setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize) {
_unusedResourcesMaxSize = clamp(unusedResourcesMaxSize, MIN_UNUSED_MAX_SIZE, MAX_UNUSED_MAX_SIZE); _unusedResourcesMaxSize = glm::clamp(unusedResourcesMaxSize, MIN_UNUSED_MAX_SIZE, MAX_UNUSED_MAX_SIZE);
reserveUnusedResource(0); reserveUnusedResource(0);
resetResourceCounters(); resetUnusedResourceCounter();
} }
void ResourceCache::addUnusedResource(const QSharedPointer<Resource>& resource) { void ResourceCache::addUnusedResource(const QSharedPointer<Resource>& resource) {
@ -391,18 +374,20 @@ void ResourceCache::addUnusedResource(const QSharedPointer<Resource>& resource)
if (resource->getBytes() == 0 || resource->getBytes() > _unusedResourcesMaxSize) { if (resource->getBytes() == 0 || resource->getBytes() > _unusedResourcesMaxSize) {
resource->setCache(nullptr); resource->setCache(nullptr);
removeResource(resource->getURL(), resource->getBytes()); removeResource(resource->getURL(), resource->getBytes());
resetResourceCounters(); resetTotalResourceCounter();
return; return;
} }
reserveUnusedResource(resource->getBytes()); reserveUnusedResource(resource->getBytes());
resource->setLRUKey(++_lastLRUKey); resource->setLRUKey(++_lastLRUKey);
_unusedResourcesSize += resource->getBytes();
resetResourceCounters(); {
QWriteLocker locker(&_unusedResourcesLock);
_unusedResources.insert(resource->getLRUKey(), resource);
_unusedResourcesSize += resource->getBytes();
}
QWriteLocker locker(&_unusedResourcesLock); resetUnusedResourceCounter();
_unusedResources.insert(resource->getLRUKey(), resource);
} }
void ResourceCache::removeUnusedResource(const QSharedPointer<Resource>& resource) { void ResourceCache::removeUnusedResource(const QSharedPointer<Resource>& resource) {
@ -412,7 +397,7 @@ void ResourceCache::removeUnusedResource(const QSharedPointer<Resource>& resourc
_unusedResourcesSize -= resource->getBytes(); _unusedResourcesSize -= resource->getBytes();
locker.unlock(); locker.unlock();
resetResourceCounters(); resetUnusedResourceCounter();
} }
} }
@ -445,14 +430,19 @@ void ResourceCache::clearUnusedResources() {
} }
_unusedResources.clear(); _unusedResources.clear();
} }
_unusedResourcesSize = 0;
} }
void ResourceCache::resetResourceCounters() { void ResourceCache::resetTotalResourceCounter() {
{ {
QReadLocker locker(&_resourcesLock); QReadLocker locker(&_resourcesLock);
_numTotalResources = _resources.size(); _numTotalResources = _resources.size();
} }
emit dirty();
}
void ResourceCache::resetUnusedResourceCounter() {
{ {
QReadLocker locker(&_unusedResourcesLock); QReadLocker locker(&_unusedResourcesLock);
_numUnusedResources = _unusedResources.size(); _numUnusedResources = _unusedResources.size();
@ -461,6 +451,13 @@ void ResourceCache::resetResourceCounters() {
emit dirty(); emit dirty();
} }
void ResourceCache::resetResourceCounters() {
resetTotalResourceCounter();
resetUnusedResourceCounter();
emit dirty();
}
void ResourceCache::removeResource(const QUrl& url, qint64 size) { void ResourceCache::removeResource(const QUrl& url, qint64 size) {
QWriteLocker locker(&_resourcesLock); QWriteLocker locker(&_resourcesLock);
_resources.remove(url); _resources.remove(url);
@ -481,38 +478,34 @@ QList<QSharedPointer<Resource>> ResourceCache::getLoadingRequests() {
return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequests(); return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequests();
} }
int ResourceCache::getPendingRequestCount() { uint32_t ResourceCache::getPendingRequestCount() {
return DependencyManager::get<ResourceCacheSharedItems>()->getPendingRequestsCount(); return DependencyManager::get<ResourceCacheSharedItems>()->getPendingRequestsCount();
} }
int ResourceCache::getLoadingRequestCount() { uint32_t ResourceCache::getLoadingRequestCount() {
return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequestsCount(); return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequestsCount();
} }
bool ResourceCache::attemptRequest(QSharedPointer<Resource> resource) { bool ResourceCache::attemptRequest(QSharedPointer<Resource> resource) {
Q_ASSERT(!resource.isNull()); Q_ASSERT(!resource.isNull());
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>(); auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
if (_requestsActive >= _requestLimit) { if (sharedItems->appendRequest(resource)) {
// wait until a slot becomes available resource->makeRequest();
sharedItems->appendPendingRequest(resource); return true;
return false;
} }
return false;
++_requestsActive;
sharedItems->appendActiveRequest(resource);
resource->makeRequest();
return true;
} }
void ResourceCache::requestCompleted(QWeakPointer<Resource> resource) { void ResourceCache::requestCompleted(QWeakPointer<Resource> resource) {
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>(); auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
sharedItems->removeRequest(resource); sharedItems->removeRequest(resource);
--_requestsActive;
attemptHighestPriorityRequest(); // Now go fill any new request spots
while (sharedItems->getLoadingRequestsCount() < sharedItems->getRequestLimit() && sharedItems->getPendingRequestsCount() > 0) {
attemptHighestPriorityRequest();
}
} }
bool ResourceCache::attemptHighestPriorityRequest() { bool ResourceCache::attemptHighestPriorityRequest() {
@ -521,10 +514,6 @@ bool ResourceCache::attemptHighestPriorityRequest() {
return (resource && attemptRequest(resource)); return (resource && attemptRequest(resource));
} }
const int DEFAULT_REQUEST_LIMIT = 10;
int ResourceCache::_requestLimit = DEFAULT_REQUEST_LIMIT;
int ResourceCache::_requestsActive = 0;
static int requestID = 0; static int requestID = 0;
Resource::Resource(const QUrl& url) : Resource::Resource(const QUrl& url) :
@ -550,7 +539,7 @@ void Resource::ensureLoading() {
} }
void Resource::setLoadPriority(const QPointer<QObject>& owner, float priority) { void Resource::setLoadPriority(const QPointer<QObject>& owner, float priority) {
if (!(_failedToLoad)) { if (!_failedToLoad) {
_loadPriorities.insert(owner, priority); _loadPriorities.insert(owner, priority);
} }
} }
@ -566,7 +555,7 @@ void Resource::setLoadPriorities(const QHash<QPointer<QObject>, float>& prioriti
} }
void Resource::clearLoadPriority(const QPointer<QObject>& owner) { void Resource::clearLoadPriority(const QPointer<QObject>& owner) {
if (!(_failedToLoad)) { if (!_failedToLoad) {
_loadPriorities.remove(owner); _loadPriorities.remove(owner);
} }
} }
@ -592,6 +581,7 @@ void Resource::refresh() {
if (_request && !(_loaded || _failedToLoad)) { if (_request && !(_loaded || _failedToLoad)) {
return; return;
} }
if (_request) { if (_request) {
_request->disconnect(this); _request->disconnect(this);
_request->deleteLater(); _request->deleteLater();
@ -613,7 +603,7 @@ void Resource::allReferencesCleared() {
if (_cache && isCacheable()) { if (_cache && isCacheable()) {
// create and reinsert new shared pointer // create and reinsert new shared pointer
QSharedPointer<Resource> self(this, &Resource::allReferencesCleared); QSharedPointer<Resource> self(this, &Resource::deleter);
setSelf(self); setSelf(self);
reinsert(); reinsert();
@ -623,7 +613,7 @@ void Resource::allReferencesCleared() {
if (_cache) { if (_cache) {
// remove from the cache // remove from the cache
_cache->removeResource(getURL(), getBytes()); _cache->removeResource(getURL(), getBytes());
_cache->resetResourceCounters(); _cache->resetTotalResourceCounter();
} }
deleteLater(); deleteLater();
@ -732,6 +722,7 @@ void Resource::handleReplyFinished() {
{ "from_cache", false }, { "from_cache", false },
{ "size_mb", _bytesTotal / 1000000.0 } { "size_mb", _bytesTotal / 1000000.0 }
}); });
ResourceCache::requestCompleted(_self);
return; return;
} }

View file

@ -66,21 +66,25 @@ class ResourceCacheSharedItems : public Dependency {
using Lock = std::unique_lock<Mutex>; using Lock = std::unique_lock<Mutex>;
public: public:
void appendPendingRequest(QWeakPointer<Resource> newRequest); bool appendRequest(QWeakPointer<Resource> newRequest);
void appendActiveRequest(QWeakPointer<Resource> newRequest);
void removeRequest(QWeakPointer<Resource> doneRequest); void removeRequest(QWeakPointer<Resource> doneRequest);
QList<QSharedPointer<Resource>> getPendingRequests(); void setRequestLimit(uint32_t limit);
uint32_t getPendingRequestsCount() const; uint32_t getRequestLimit() const;
QList<QSharedPointer<Resource>> getLoadingRequests(); QList<QSharedPointer<Resource>> getPendingRequests() const;
QSharedPointer<Resource> getHighestPendingRequest(); QSharedPointer<Resource> getHighestPendingRequest();
uint32_t getPendingRequestsCount() const;
QList<QSharedPointer<Resource>> getLoadingRequests() const;
uint32_t getLoadingRequestsCount() const; uint32_t getLoadingRequestsCount() const;
void clear();
private: private:
ResourceCacheSharedItems() = default; ResourceCacheSharedItems() = default;
mutable Mutex _mutex; mutable Mutex _mutex;
QList<QWeakPointer<Resource>> _pendingRequests; QList<QWeakPointer<Resource>> _pendingRequests;
QList<QWeakPointer<Resource>> _loadingRequests; QList<QSharedPointer<Resource>> _loadingRequests;
const uint32_t DEFAULT_REQUEST_LIMIT = 10;
uint32_t _requestLimit { DEFAULT_REQUEST_LIMIT };
}; };
/// Wrapper to expose resources to JS/QML /// Wrapper to expose resources to JS/QML
@ -200,25 +204,20 @@ public:
Q_INVOKABLE QVariantList getResourceList(); Q_INVOKABLE QVariantList getResourceList();
static void setRequestLimit(int limit); static void setRequestLimit(uint32_t limit);
static int getRequestLimit() { return _requestLimit; } static uint32_t getRequestLimit() { return DependencyManager::get<ResourceCacheSharedItems>()->getRequestLimit(); }
static int getRequestsActive() { return _requestsActive; }
void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize); void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize);
qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; } qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; }
static QList<QSharedPointer<Resource>> getLoadingRequests(); static QList<QSharedPointer<Resource>> getLoadingRequests();
static uint32_t getPendingRequestCount();
static int getPendingRequestCount(); static uint32_t getLoadingRequestCount();
static int getLoadingRequestCount();
ResourceCache(QObject* parent = nullptr); ResourceCache(QObject* parent = nullptr);
virtual ~ResourceCache(); virtual ~ResourceCache();
void refreshAll(); void refreshAll();
void refresh(const QUrl& url);
void clearUnusedResources(); void clearUnusedResources();
signals: signals:
@ -272,11 +271,11 @@ private:
friend class ScriptableResourceCache; friend class ScriptableResourceCache;
void reserveUnusedResource(qint64 resourceSize); void reserveUnusedResource(qint64 resourceSize);
void resetResourceCounters();
void removeResource(const QUrl& url, qint64 size = 0); void removeResource(const QUrl& url, qint64 size = 0);
static int _requestLimit; void resetTotalResourceCounter();
static int _requestsActive; void resetUnusedResourceCounter();
void resetResourceCounters();
// Resources // Resources
QHash<QUrl, QWeakPointer<Resource>> _resources; QHash<QUrl, QWeakPointer<Resource>> _resources;
@ -293,10 +292,6 @@ private:
std::atomic<size_t> _numUnusedResources { 0 }; std::atomic<size_t> _numUnusedResources { 0 };
std::atomic<qint64> _unusedResourcesSize { 0 }; std::atomic<qint64> _unusedResourcesSize { 0 };
// Pending resources
QQueue<QUrl> _resourcesToBeGotten;
QReadWriteLock _resourcesToBeGottenLock { QReadWriteLock::Recursive };
}; };
/// Wrapper to expose resource caches to JS/QML /// Wrapper to expose resource caches to JS/QML
@ -455,7 +450,7 @@ protected:
virtual void makeRequest(); virtual void makeRequest();
/// Checks whether the resource is cacheable. /// Checks whether the resource is cacheable.
virtual bool isCacheable() const { return true; } virtual bool isCacheable() const { return _loaded; }
/// Called when the download has finished. /// Called when the download has finished.
/// This should be overridden by subclasses that need to process the data once it is downloaded. /// This should be overridden by subclasses that need to process the data once it is downloaded.