mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 02:04:28 +02:00
Make script cache thread safe
This commit is contained in:
parent
f97e61e305
commit
ee017cf0a5
2 changed files with 42 additions and 12 deletions
|
@ -28,21 +28,26 @@ ScriptCache::ScriptCache(QObject* parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptCache::clearCache() {
|
void ScriptCache::clearCache() {
|
||||||
|
Lock lock(_containerLock);
|
||||||
_scriptCache.clear();
|
_scriptCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUser, bool& isPending, bool reload) {
|
QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUser, bool& isPending, bool reload) {
|
||||||
QUrl url = ResourceManager::normalizeURL(unnormalizedURL);
|
QUrl url = ResourceManager::normalizeURL(unnormalizedURL);
|
||||||
QString scriptContents;
|
QString scriptContents;
|
||||||
|
|
||||||
|
Lock lock(_containerLock);
|
||||||
if (_scriptCache.contains(url) && !reload) {
|
if (_scriptCache.contains(url) && !reload) {
|
||||||
qCDebug(scriptengine) << "Found script in cache:" << url.toString();
|
qCDebug(scriptengine) << "Found script in cache:" << url.toString();
|
||||||
scriptContents = _scriptCache[url];
|
scriptContents = _scriptCache[url];
|
||||||
|
lock.unlock();
|
||||||
scriptUser->scriptContentsAvailable(url, scriptContents);
|
scriptUser->scriptContentsAvailable(url, scriptContents);
|
||||||
isPending = false;
|
isPending = false;
|
||||||
} else {
|
} else {
|
||||||
isPending = true;
|
isPending = true;
|
||||||
bool alreadyWaiting = _scriptUsers.contains(url);
|
bool alreadyWaiting = _scriptUsers.contains(url);
|
||||||
_scriptUsers.insert(url, scriptUser);
|
_scriptUsers.insert(url, scriptUser);
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
if (alreadyWaiting) {
|
if (alreadyWaiting) {
|
||||||
qCDebug(scriptengine) << "Already downloading script at:" << url.toString();
|
qCDebug(scriptengine) << "Already downloading script at:" << url.toString();
|
||||||
|
@ -58,6 +63,7 @@ QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUs
|
||||||
|
|
||||||
void ScriptCache::deleteScript(const QUrl& unnormalizedURL) {
|
void ScriptCache::deleteScript(const QUrl& unnormalizedURL) {
|
||||||
QUrl url = ResourceManager::normalizeURL(unnormalizedURL);
|
QUrl url = ResourceManager::normalizeURL(unnormalizedURL);
|
||||||
|
Lock lock(_containerLock);
|
||||||
if (_scriptCache.contains(url)) {
|
if (_scriptCache.contains(url)) {
|
||||||
qCDebug(scriptengine) << "Delete script from cache:" << url.toString();
|
qCDebug(scriptengine) << "Delete script from cache:" << url.toString();
|
||||||
_scriptCache.remove(url);
|
_scriptCache.remove(url);
|
||||||
|
@ -67,17 +73,22 @@ void ScriptCache::deleteScript(const QUrl& unnormalizedURL) {
|
||||||
void ScriptCache::scriptDownloaded() {
|
void ScriptCache::scriptDownloaded() {
|
||||||
ResourceRequest* req = qobject_cast<ResourceRequest*>(sender());
|
ResourceRequest* req = qobject_cast<ResourceRequest*>(sender());
|
||||||
QUrl url = req->getUrl();
|
QUrl url = req->getUrl();
|
||||||
|
|
||||||
|
Lock lock(_containerLock);
|
||||||
QList<ScriptUser*> scriptUsers = _scriptUsers.values(url);
|
QList<ScriptUser*> scriptUsers = _scriptUsers.values(url);
|
||||||
_scriptUsers.remove(url);
|
_scriptUsers.remove(url);
|
||||||
|
|
||||||
if (req->getResult() == ResourceRequest::Success) {
|
if (req->getResult() == ResourceRequest::Success) {
|
||||||
_scriptCache[url] = req->getData();
|
auto scriptContents = req->getData();
|
||||||
|
_scriptCache[url] = scriptContents;
|
||||||
|
lock.unlock();
|
||||||
qCDebug(scriptengine) << "Done downloading script at:" << url.toString();
|
qCDebug(scriptengine) << "Done downloading script at:" << url.toString();
|
||||||
|
|
||||||
foreach(ScriptUser* user, scriptUsers) {
|
foreach(ScriptUser* user, scriptUsers) {
|
||||||
user->scriptContentsAvailable(url, _scriptCache[url]);
|
user->scriptContentsAvailable(url, scriptContents);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
lock.unlock();
|
||||||
qCWarning(scriptengine) << "Error loading script from URL " << url;
|
qCWarning(scriptengine) << "Error loading script from URL " << url;
|
||||||
foreach(ScriptUser* user, scriptUsers) {
|
foreach(ScriptUser* user, scriptUsers) {
|
||||||
user->errorInLoadingScript(url);
|
user->errorInLoadingScript(url);
|
||||||
|
@ -99,15 +110,19 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lock lock(_containerLock);
|
||||||
if (_scriptCache.contains(url) && !forceDownload) {
|
if (_scriptCache.contains(url) && !forceDownload) {
|
||||||
|
auto scriptContent = _scriptCache[url];
|
||||||
|
lock.unlock();
|
||||||
qCDebug(scriptengine) << "Found script in cache:" << url.toString();
|
qCDebug(scriptengine) << "Found script in cache:" << url.toString();
|
||||||
#if 1 // def THREAD_DEBUGGING
|
#if 1 // def THREAD_DEBUGGING
|
||||||
qCDebug(scriptengine) << "ScriptCache::getScriptContents() about to call contentAvailable() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";
|
qCDebug(scriptengine) << "ScriptCache::getScriptContents() about to call contentAvailable() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";
|
||||||
#endif
|
#endif
|
||||||
contentAvailable(url.toString(), _scriptCache[url], true, true);
|
contentAvailable(url.toString(), scriptContent, true, true);
|
||||||
} else {
|
} else {
|
||||||
bool alreadyWaiting = _contentCallbacks.contains(url);
|
bool alreadyWaiting = _contentCallbacks.contains(url);
|
||||||
_contentCallbacks.insert(url, contentAvailable);
|
_contentCallbacks.insert(url, contentAvailable);
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
if (alreadyWaiting) {
|
if (alreadyWaiting) {
|
||||||
qCDebug(scriptengine) << "Already downloading script at:" << url.toString();
|
qCDebug(scriptengine) << "Already downloading script at:" << url.toString();
|
||||||
|
@ -129,19 +144,29 @@ void ScriptCache::scriptContentAvailable() {
|
||||||
#endif
|
#endif
|
||||||
ResourceRequest* req = qobject_cast<ResourceRequest*>(sender());
|
ResourceRequest* req = qobject_cast<ResourceRequest*>(sender());
|
||||||
QUrl url = req->getUrl();
|
QUrl url = req->getUrl();
|
||||||
QList<contentAvailableCallback> allCallbacks = _contentCallbacks.values(url);
|
|
||||||
_contentCallbacks.remove(url);
|
|
||||||
|
|
||||||
bool success = req->getResult() == ResourceRequest::Success;
|
QString scriptContent;
|
||||||
|
QList<contentAvailableCallback> allCallbacks;
|
||||||
|
bool success { false };
|
||||||
|
|
||||||
if (success) {
|
{
|
||||||
_scriptCache[url] = req->getData();
|
Lock lock(_containerLock);
|
||||||
qCDebug(scriptengine) << "Done downloading script at:" << url.toString();
|
allCallbacks = _contentCallbacks.values(url);
|
||||||
} else {
|
_contentCallbacks.remove(url);
|
||||||
qCWarning(scriptengine) << "Error loading script from URL " << url;
|
success = req->getResult() == ResourceRequest::Success;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
_scriptCache[url] = scriptContent = req->getData();
|
||||||
|
qCDebug(scriptengine) << "Done downloading script at:" << url.toString();
|
||||||
|
} else {
|
||||||
|
// Dubious, but retained here because it matches the behavior before fixing the threading
|
||||||
|
scriptContent = _scriptCache[url];
|
||||||
|
qCWarning(scriptengine) << "Error loading script from URL " << url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(contentAvailableCallback thisCallback, allCallbacks) {
|
foreach(contentAvailableCallback thisCallback, allCallbacks) {
|
||||||
thisCallback(url.toString(), _scriptCache[url], true, success);
|
thisCallback(url.toString(), scriptContent, true, success);
|
||||||
}
|
}
|
||||||
req->deleteLater();
|
req->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#ifndef hifi_ScriptCache_h
|
#ifndef hifi_ScriptCache_h
|
||||||
#define hifi_ScriptCache_h
|
#define hifi_ScriptCache_h
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
#include <ResourceCache.h>
|
#include <ResourceCache.h>
|
||||||
|
|
||||||
class ScriptUser {
|
class ScriptUser {
|
||||||
|
@ -27,6 +28,9 @@ class ScriptCache : public QObject, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
|
using Mutex = std::mutex;
|
||||||
|
using Lock = std::unique_lock<Mutex>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void clearCache();
|
void clearCache();
|
||||||
void getScriptContents(const QString& scriptOrURL, contentAvailableCallback contentAvailable, bool forceDownload = false);
|
void getScriptContents(const QString& scriptOrURL, contentAvailableCallback contentAvailable, bool forceDownload = false);
|
||||||
|
@ -46,6 +50,7 @@ private slots:
|
||||||
private:
|
private:
|
||||||
ScriptCache(QObject* parent = NULL);
|
ScriptCache(QObject* parent = NULL);
|
||||||
|
|
||||||
|
Mutex _containerLock;
|
||||||
QMultiMap<QUrl, contentAvailableCallback> _contentCallbacks;
|
QMultiMap<QUrl, contentAvailableCallback> _contentCallbacks;
|
||||||
|
|
||||||
QHash<QUrl, QString> _scriptCache;
|
QHash<QUrl, QString> _scriptCache;
|
||||||
|
|
Loading…
Reference in a new issue