History

Make script cache thread safe

Brad Davis committed 10 years ago

Commit ee017cf1 parent f97e61e2 files · +42 −12Browse files

Showing the changes to libraries/script-engine/src/ScriptCache.cpp (1 of 2 files). Show all

Unified · Split

libraries/script-engine/src/ScriptCache.cpp+37−12
@@ -28,21 +28,26 @@ ScriptCache::ScriptCache(QObject* parent) { · 27 unmodified lines
28}28}
29 29
30void ScriptCache::clearCache() {30void ScriptCache::clearCache() {
31 Lock lock(_containerLock);
31 _scriptCache.clear();32 _scriptCache.clear();
32}33}
33 34
34QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUser, bool& isPending, bool reload) {35QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUser, bool& isPending, bool reload) {
35 QUrl url = ResourceManager::normalizeURL(unnormalizedURL);36 QUrl url = ResourceManager::normalizeURL(unnormalizedURL);
36 QString scriptContents;37 QString scriptContents;
38
39 Lock lock(_containerLock);
37 if (_scriptCache.contains(url) && !reload) {40 if (_scriptCache.contains(url) && !reload) {
38 qCDebug(scriptengine) << "Found script in cache:" << url.toString();41 qCDebug(scriptengine) << "Found script in cache:" << url.toString();
39 scriptContents = _scriptCache[url];42 scriptContents = _scriptCache[url];
43 lock.unlock();
40 scriptUser->scriptContentsAvailable(url, scriptContents);44 scriptUser->scriptContentsAvailable(url, scriptContents);
41 isPending = false;45 isPending = false;
42 } else {46 } else {
43 isPending = true;47 isPending = true;
44 bool alreadyWaiting = _scriptUsers.contains(url);48 bool alreadyWaiting = _scriptUsers.contains(url);
45 _scriptUsers.insert(url, scriptUser);49 _scriptUsers.insert(url, scriptUser);
50 lock.unlock();
46 51
47 if (alreadyWaiting) {52 if (alreadyWaiting) {
48 qCDebug(scriptengine) << "Already downloading script at:" << url.toString();53 qCDebug(scriptengine) << "Already downloading script at:" << url.toString();
@@ -58,6 +63,7 @@ QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUs · 9 unmodified lines
58 63
59void ScriptCache::deleteScript(const QUrl& unnormalizedURL) {64void ScriptCache::deleteScript(const QUrl& unnormalizedURL) {
60 QUrl url = ResourceManager::normalizeURL(unnormalizedURL);65 QUrl url = ResourceManager::normalizeURL(unnormalizedURL);
66 Lock lock(_containerLock);
61 if (_scriptCache.contains(url)) {67 if (_scriptCache.contains(url)) {
62 qCDebug(scriptengine) << "Delete script from cache:" << url.toString();68 qCDebug(scriptengine) << "Delete script from cache:" << url.toString();
63 _scriptCache.remove(url);69 _scriptCache.remove(url);
@@ -67,17 +73,22 @@ void ScriptCache::deleteScript(const QUrl& unnormalizedURL) { · 3 unmodified lines
67void ScriptCache::scriptDownloaded() {73void ScriptCache::scriptDownloaded() {
68 ResourceRequest* req = qobject_cast<ResourceRequest*>(sender());74 ResourceRequest* req = qobject_cast<ResourceRequest*>(sender());
69 QUrl url = req->getUrl();75 QUrl url = req->getUrl();
76
77 Lock lock(_containerLock);
70 QList<ScriptUser*> scriptUsers = _scriptUsers.values(url);78 QList<ScriptUser*> scriptUsers = _scriptUsers.values(url);
71 _scriptUsers.remove(url);79 _scriptUsers.remove(url);
72 80
73 if (req->getResult() == ResourceRequest::Success) {81 if (req->getResult() == ResourceRequest::Success) {
74 _scriptCache[url] = req->getData();82 auto scriptContents = req->getData();
83 _scriptCache[url] = scriptContents;
84 lock.unlock();
75 qCDebug(scriptengine) << "Done downloading script at:" << url.toString();85 qCDebug(scriptengine) << "Done downloading script at:" << url.toString();
76 86
77 foreach(ScriptUser* user, scriptUsers) {87 foreach(ScriptUser* user, scriptUsers) {
78 user->scriptContentsAvailable(url, _scriptCache[url]);88 user->scriptContentsAvailable(url, scriptContents);
79 }89 }
80 } else {90 } else {
91 lock.unlock();
81 qCWarning(scriptengine) << "Error loading script from URL " << url;92 qCWarning(scriptengine) << "Error loading script from URL " << url;
82 foreach(ScriptUser* user, scriptUsers) {93 foreach(ScriptUser* user, scriptUsers) {
83 user->errorInLoadingScript(url);94 user->errorInLoadingScript(url);
@@ -99,15 +110,19 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable · 15 unmodified lines
99 return;110 return;
100 }111 }
101 112
113 Lock lock(_containerLock);
102 if (_scriptCache.contains(url) && !forceDownload) {114 if (_scriptCache.contains(url) && !forceDownload) {
115 auto scriptContent = _scriptCache[url];
116 lock.unlock();
103 qCDebug(scriptengine) << "Found script in cache:" << url.toString();117 qCDebug(scriptengine) << "Found script in cache:" << url.toString();
104 #if 1 // def THREAD_DEBUGGING118 #if 1 // def THREAD_DEBUGGING
105 qCDebug(scriptengine) << "ScriptCache::getScriptContents() about to call contentAvailable() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";119 qCDebug(scriptengine) << "ScriptCache::getScriptContents() about to call contentAvailable() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";
106 #endif120 #endif
107 contentAvailable(url.toString(), _scriptCache[url], true, true);121 contentAvailable(url.toString(), scriptContent, true, true);
108 } else {122 } else {
109 bool alreadyWaiting = _contentCallbacks.contains(url);123 bool alreadyWaiting = _contentCallbacks.contains(url);
110 _contentCallbacks.insert(url, contentAvailable);124 _contentCallbacks.insert(url, contentAvailable);
125 lock.unlock();
111 126
112 if (alreadyWaiting) {127 if (alreadyWaiting) {
113 qCDebug(scriptengine) << "Already downloading script at:" << url.toString();128 qCDebug(scriptengine) << "Already downloading script at:" << url.toString();
@@ -129,19 +144,29 @@ void ScriptCache::scriptContentAvailable() { · 15 unmodified lines
129 #endif144 #endif
130 ResourceRequest* req = qobject_cast<ResourceRequest*>(sender());145 ResourceRequest* req = qobject_cast<ResourceRequest*>(sender());
131 QUrl url = req->getUrl();146 QUrl url = req->getUrl();
132 QList<contentAvailableCallback> allCallbacks = _contentCallbacks.values(url);
133 _contentCallbacks.remove(url);
134 147
135 bool success = req->getResult() == ResourceRequest::Success;148 QString scriptContent;
149 QList<contentAvailableCallback> allCallbacks;
150 bool success { false };
136 151
137 if (success) {152 {
138 _scriptCache[url] = req->getData();153 Lock lock(_containerLock);
139 qCDebug(scriptengine) << "Done downloading script at:" << url.toString();154 allCallbacks = _contentCallbacks.values(url);
140 } else {155 _contentCallbacks.remove(url);
141 qCWarning(scriptengine) << "Error loading script from URL " << url;156 success = req->getResult() == ResourceRequest::Success;
157
158 if (success) {
159 _scriptCache[url] = scriptContent = req->getData();
160 qCDebug(scriptengine) << "Done downloading script at:" << url.toString();
161 } else {
162 // Dubious, but retained here because it matches the behavior before fixing the threading
163 scriptContent = _scriptCache[url];
164 qCWarning(scriptengine) << "Error loading script from URL " << url;
165 }
142 }166 }
167
143 foreach(contentAvailableCallback thisCallback, allCallbacks) {168 foreach(contentAvailableCallback thisCallback, allCallbacks) {
144 thisCallback(url.toString(), _scriptCache[url], true, success);169 thisCallback(url.toString(), scriptContent, true, success);
145 }170 }
146 req->deleteLater();171 req->deleteLater();
147}172}