Merge pull request #7392 from jherico/resource

Make shared lists thread safe
This commit is contained in:
Chris Collins 2016-03-18 13:25:58 -07:00
commit 5e8c10508c
2 changed files with 89 additions and 36 deletions

View file

@ -159,44 +159,45 @@ void ResourceCache::clearUnusedResource() {
} }
} }
bool ResourceCache::attemptRequest(Resource* resource) { void ResourceCacheSharedItems::appendActiveRequest(Resource* resource) {
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>(); Lock lock(_mutex);
_loadingRequests.append(resource);
// Disable request limiting for ATP
if (resource->getURL().scheme() != URL_SCHEME_ATP) {
if (_requestsActive >= _requestLimit) {
// wait until a slot becomes available
sharedItems->_pendingRequests.append(resource);
return false;
}
++_requestsActive;
}
sharedItems->_loadingRequests.append(resource);
resource->makeRequest();
return true;
} }
void ResourceCache::requestCompleted(Resource* resource) { void ResourceCacheSharedItems::appendPendingRequest(Resource* resource) {
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>(); Lock lock(_mutex);
sharedItems->_loadingRequests.removeOne(resource); _pendingRequests.append(resource);
if (resource->getURL().scheme() != URL_SCHEME_ATP) {
--_requestsActive;
}
attemptHighestPriorityRequest();
} }
bool ResourceCache::attemptHighestPriorityRequest() { QList<QPointer<Resource>> ResourceCacheSharedItems::getPendingRequests() const {
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>(); Lock lock(_mutex);
return _pendingRequests;
}
uint32_t ResourceCacheSharedItems::getPendingRequestsCount() const {
Lock lock(_mutex);
return _pendingRequests.size();
}
QList<Resource*> ResourceCacheSharedItems::getLoadingRequests() const {
Lock lock(_mutex);
return _loadingRequests;
}
void ResourceCacheSharedItems::removeRequest(Resource* resource) {
Lock lock(_mutex);
_loadingRequests.removeOne(resource);
}
Resource* ResourceCacheSharedItems::getHighestPendingRequest() {
Lock lock(_mutex);
// look for the highest priority pending request // look for the highest priority pending request
int highestIndex = -1; int highestIndex = -1;
float highestPriority = -FLT_MAX; float highestPriority = -FLT_MAX;
for (int i = 0; i < sharedItems->_pendingRequests.size(); ) { for (int i = 0; i < _pendingRequests.size();) {
Resource* resource = sharedItems->_pendingRequests.at(i).data(); Resource* resource = _pendingRequests.at(i).data();
if (!resource) { if (!resource) {
sharedItems->_pendingRequests.removeAt(i); _pendingRequests.removeAt(i);
continue; continue;
} }
float priority = resource->getLoadPriority(); float priority = resource->getLoadPriority();
@ -206,7 +207,45 @@ bool ResourceCache::attemptHighestPriorityRequest() {
} }
i++; i++;
} }
return (highestIndex >= 0) && attemptRequest(sharedItems->_pendingRequests.takeAt(highestIndex)); if (highestIndex >= 0) {
return _pendingRequests.takeAt(highestIndex);
}
return nullptr;
}
bool ResourceCache::attemptRequest(Resource* resource) {
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
// Disable request limiting for ATP
if (resource->getURL().scheme() != URL_SCHEME_ATP) {
if (_requestsActive >= _requestLimit) {
// wait until a slot becomes available
sharedItems->appendPendingRequest(resource);
return false;
}
++_requestsActive;
}
sharedItems->appendActiveRequest(resource);
resource->makeRequest();
return true;
}
void ResourceCache::requestCompleted(Resource* resource) {
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
sharedItems->removeRequest(resource);
if (resource->getURL().scheme() != URL_SCHEME_ATP) {
--_requestsActive;
}
attemptHighestPriorityRequest();
}
bool ResourceCache::attemptHighestPriorityRequest() {
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
auto resource = sharedItems->getHighestPendingRequest();
return (resource && attemptRequest(resource));
} }
const int DEFAULT_REQUEST_LIMIT = 10; const int DEFAULT_REQUEST_LIMIT = 10;

View file

@ -12,6 +12,7 @@
#ifndef hifi_ResourceCache_h #ifndef hifi_ResourceCache_h
#define hifi_ResourceCache_h #define hifi_ResourceCache_h
#include <mutex>
#include <QtCore/QHash> #include <QtCore/QHash>
#include <QtCore/QList> #include <QtCore/QList>
#include <QtCore/QObject> #include <QtCore/QObject>
@ -53,12 +54,25 @@ static const qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES;
// object instead // object instead
class ResourceCacheSharedItems : public Dependency { class ResourceCacheSharedItems : public Dependency {
SINGLETON_DEPENDENCY SINGLETON_DEPENDENCY
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
public: public:
QList<QPointer<Resource>> _pendingRequests; void appendPendingRequest(Resource* newRequest);
QList<Resource*> _loadingRequests; void appendActiveRequest(Resource* newRequest);
void removeRequest(Resource* doneRequest);
QList<QPointer<Resource>> getPendingRequests() const;
uint32_t getPendingRequestsCount() const;
QList<Resource*> getLoadingRequests() const;
Resource* getHighestPendingRequest();
private: private:
ResourceCacheSharedItems() { } ResourceCacheSharedItems() { }
virtual ~ResourceCacheSharedItems() { } virtual ~ResourceCacheSharedItems() { }
mutable Mutex _mutex;
QList<QPointer<Resource>> _pendingRequests;
QList<Resource*> _loadingRequests;
}; };
@ -75,11 +89,11 @@ public:
void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize); void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize);
qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; } qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; }
static const QList<Resource*>& getLoadingRequests() static const QList<Resource*> getLoadingRequests()
{ return DependencyManager::get<ResourceCacheSharedItems>()->_loadingRequests; } { return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequests(); }
static int getPendingRequestCount() static int getPendingRequestCount()
{ return DependencyManager::get<ResourceCacheSharedItems>()->_pendingRequests.size(); } { return DependencyManager::get<ResourceCacheSharedItems>()->getPendingRequestsCount(); }
ResourceCache(QObject* parent = NULL); ResourceCache(QObject* parent = NULL);
virtual ~ResourceCache(); virtual ~ResourceCache();