History

Add lock around _entityScripts

Clement committed 8 years ago

Commit e6b4cce1 parent d5456ed2 files · +82 −26Browse files

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

Unified · Split

libraries/script-engine/src/ScriptEngine.cpp+77−25
@@ -1974,8 +1974,9 @@ void ScriptEngine::forwardHandlerCall(const EntityItemID& entityID, const QStrin · 1973 unmodified lines
19741974 }
19751975
19761976 int ScriptEngine::getNumRunningEntityScripts() const {
1977+ QReadLocker locker { &_entityScriptsLock };
19771978 int sum = 0;
1978− for (auto& st : _entityScripts) {
1979+ for (const auto& st : _entityScripts) {
19791980 if (st.status == EntityScriptStatus::RUNNING) {
19801981 ++sum;
19811982 }
@@ -1984,14 +1985,20 @@ int ScriptEngine::getNumRunningEntityScripts() const { · 2 unmodified lines
19841985 }
19851986
19861987 void ScriptEngine::setEntityScriptDetails(const EntityItemID& entityID, const EntityScriptDetails& details) {
1987− _entityScripts[entityID] = details;
1988+ {
1989+ QWriteLocker locker { &_entityScriptsLock };
1990+ _entityScripts[entityID] = details;
1991+ }
19881992 emit entityScriptDetailsUpdated();
19891993 }
19901994
19911995 void ScriptEngine::updateEntityScriptStatus(const EntityItemID& entityID, const EntityScriptStatus &status, const QString& errorInfo) {
1992− EntityScriptDetails &details = _entityScripts[entityID];
1993− details.status = status;
1994− details.errorInfo = errorInfo;
1996+ {
1997+ QWriteLocker locker { &_entityScriptsLock };
1998+ EntityScriptDetails& details = _entityScripts[entityID];
1999+ details.status = status;
2000+ details.errorInfo = errorInfo;
2001+ }
19952002 emit entityScriptDetailsUpdated();
19962003 }
19972004
@@ -2042,6 +2049,7 @@ QFuture<QVariant> ScriptEngine::getLocalEntityScriptDetails(const EntityItemID& · 44 unmodified lines
20422049 }
20432050
20442051 bool ScriptEngine::getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const {
2052+ QReadLocker locker { &_entityScriptsLock };
20452053 auto it = _entityScripts.constFind(entityID);
20462054 if (it == _entityScripts.constEnd()) {
20472055 return false;
@@ -2050,6 +2058,11 @@ bool ScriptEngine::getEntityScriptDetails(const EntityItemID& entityID, EntitySc · 2 unmodified lines
20502058 return true;
20512059 }
20522060
2061+bool ScriptEngine::hasEntityScriptDetails(const EntityItemID& entityID) const {
2062+ QReadLocker locker { &_entityScriptsLock };
2063+ return _entityScripts.contains(entityID);
2064+}
2065+
20532066 const static EntityItemID BAD_SCRIPT_UUID_PLACEHOLDER { "{20170224-dead-face-0000-cee000021114}" };
20542067
20552068 void ScriptEngine::processDeferredEntityLoads(const QString& entityScript, const EntityItemID& leaderID) {
@@ -2064,14 +2077,15 @@ void ScriptEngine::processDeferredEntityLoads(const QString& entityScript, const · 8 unmodified lines
20642077 }
20652078 foreach(DeferredLoadEntity retry, retryLoads) {
20662079 // check whether entity was since been deleted
2067− if (!_entityScripts.contains(retry.entityID)) {
2080+
2081+ EntityScriptDetails details;
2082+ if (!getEntityScriptDetails(retry.entityID, details)) {
20682083 qCDebug(scriptengine) << "processDeferredEntityLoads -- entity details gone (entity deleted?)"
20692084 << retry.entityID;
20702085 continue;
20712086 }
20722087
20732088 // check whether entity has since been unloaded or otherwise errored-out
2074− auto details = _entityScripts[retry.entityID];
20752089 if (details.status != EntityScriptStatus::PENDING) {
20762090 qCDebug(scriptengine) << "processDeferredEntityLoads -- entity status no longer PENDING; "
20772091 << retry.entityID << details.status;
@@ -2079,7 +2093,11 @@ void ScriptEngine::processDeferredEntityLoads(const QString& entityScript, const · 1 unmodified line
20792093 }
20802094
20812095 // propagate leader's failure reasons to the pending entity
2082− const auto leaderDetails = _entityScripts[leaderID];
2096+ EntityScriptDetails leaderDetails;
2097+ {
2098+ QWriteLocker locker { &_entityScriptsLock };
2099+ leaderDetails = _entityScripts[leaderID];
2100+ }
20832101 if (leaderDetails.status != EntityScriptStatus::RUNNING) {
20842102 qCDebug(scriptengine) << QString("... pending load of %1 cancelled (leader: %2 status: %3)")
20852103 .arg(retry.entityID.toString()).arg(leaderID.toString()).arg(leaderDetails.status);
@@ -2125,7 +2143,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& · 39 unmodified lines
21252143 return;
21262144 }
21272145
2128− if (!_entityScripts.contains(entityID)) {
2146+ if (!hasEntityScriptDetails(entityID)) {
21292147 // make sure EntityScriptDetails has an entry for this UUID right away
21302148 // (which allows bailing from the loading/provisioning process early if the Entity gets deleted mid-flight)
21312149 updateEntityScriptStatus(entityID, EntityScriptStatus::PENDING, "...pending...");
@@ -2166,9 +2184,12 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& · 34 unmodified lines
21662184 _occupiedScriptURLs[entityScript] = entityID;
21672185
21682186 #ifdef DEBUG_ENTITY_STATES
2169− auto previousStatus = _entityScripts.contains(entityID) ? _entityScripts[entityID].status : EntityScriptStatus::PENDING;
2170− qCDebug(scriptengine) << "loadEntityScript.LOADING: " << entityScript << entityID.toString()
2171− << "(previous: " << previousStatus << ")";
2187+ {
2188+ EntityScriptDetails details;
2189+ bool hasEntityScript = getEntityScriptDetails(entityID, details);
2190+ qCDebug(scriptengine) << "loadEntityScript.LOADING: " << entityScript << entityID.toString()
2191+ << "(previous: " << (hasEntityScript ? details.status : EntityScriptStatus::PENDING) << ")";
2192+ }
21722193 #endif
21732194
21742195 EntityScriptDetails newDetails;
@@ -2197,7 +2218,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& · 22 unmodified lines
21972218 #ifdef DEBUG_ENTITY_STATES
21982219 qCDebug(scriptengine) << "loadEntityScript.contentAvailable" << status << QUrl(url).fileName() << entityID.toString();
21992220 #endif
2200− if (!isStopping() && _entityScripts.contains(entityID)) {
2221+ if (!isStopping() && hasEntityScriptDetails(entityID)) {
22012222 _contentAvailableQueue[entityID] = { entityID, url, contents, isURL, success, status };
22022223 } else {
22032224 #ifdef DEBUG_ENTITY_STATES
@@ -2267,8 +2288,11 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co · 63 unmodified lines
22672288 bool isFileUrl = isURL && scriptOrURL.startsWith("file://");
22682289 auto fileName = isURL ? scriptOrURL : "about:EmbeddedEntityScript";
22692290
2270− const EntityScriptDetails &oldDetails = _entityScripts[entityID];
2271− const QString entityScript = oldDetails.scriptText;
2291+ QString entityScript;
2292+ {
2293+ QWriteLocker locker { &_entityScriptsLock };
2294+ entityScript = _entityScripts[entityID].scriptText;
2295+ }
22722296
22732297 EntityScriptDetails newDetails;
22742298 newDetails.scriptText = scriptOrURL;
@@ -2446,8 +2470,8 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldR · 171 unmodified lines
24462470 "entityID:" << entityID;
24472471 #endif
24482472
2449− if (_entityScripts.contains(entityID)) {
2450− const EntityScriptDetails &oldDetails = _entityScripts[entityID];
2473+ EntityScriptDetails oldDetails;
2474+ if (getEntityScriptDetails(entityID, oldDetails)) {
24512475 auto scriptText = oldDetails.scriptText;
24522476
24532477 if (isEntityScriptRunning(entityID)) {
@@ -2460,7 +2484,10 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldR · 6 unmodified lines
24602484 #endif
24612485 if (shouldRemoveFromMap) {
24622486 // this was a deleted entity, we've been asked to remove it from the map
2463− _entityScripts.remove(entityID);
2487+ {
2488+ QWriteLocker locker { &_entityScriptsLock };
2489+ _entityScripts.remove(entityID);
2490+ }
24642491 emit entityScriptDetailsUpdated();
24652492 } else if (oldDetails.status != EntityScriptStatus::UNLOADED) {
24662493 EntityScriptDetails newDetails;
@@ -2491,10 +2518,19 @@ void ScriptEngine::unloadAllEntityScripts() { · 24 unmodified lines
24912518 #ifdef THREAD_DEBUGGING
24922519 qCDebug(scriptengine) << "ScriptEngine::unloadAllEntityScripts() called on correct thread [" << thread() << "]";
24932520 #endif
2494− foreach(const EntityItemID& entityID, _entityScripts.keys()) {
2521+
2522+ QList<EntityItemID> keys;
2523+ {
2524+ QReadLocker locker{ &_entityScriptsLock };
2525+ keys = _entityScripts.keys();
2526+ }
2527+ foreach(const EntityItemID& entityID, keys) {
24952528 unloadEntityScript(entityID);
24962529 }
2497− _entityScripts.clear();
2530+ {
2531+ QWriteLocker locker{ &_entityScriptsLock };
2532+ _entityScripts.clear();
2533+ }
24982534 emit entityScriptDetailsUpdated();
24992535 _occupiedScriptURLs.clear();
25002536
@@ -2508,7 +2544,7 @@ void ScriptEngine::unloadAllEntityScripts() { · 7 unmodified lines
25082544 }
25092545
25102546 void ScriptEngine::refreshFileScript(const EntityItemID& entityID) {
2511− if (!HIFI_AUTOREFRESH_FILE_SCRIPTS || !_entityScripts.contains(entityID)) {
2547+ if (!HIFI_AUTOREFRESH_FILE_SCRIPTS || !hasEntityScriptDetails(entityID)) {
25122548 return;
25132549 }
25142550
@@ -2518,7 +2554,11 @@ void ScriptEngine::refreshFileScript(const EntityItemID& entityID) { · 3 unmodified lines
25182554 }
25192555 recurseGuard = true;
25202556
2521− EntityScriptDetails details = _entityScripts[entityID];
2557+ EntityScriptDetails details;
2558+ {
2559+ QWriteLocker locker { &_entityScriptsLock };
2560+ details = _entityScripts[entityID];
2561+ }
25222562 // Check to see if a file based script needs to be reloaded (easier debugging)
25232563 if (details.lastModified > 0) {
25242564 QString filePath = QUrl(details.scriptText).toLocalFile();
@@ -2584,7 +2624,11 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 59 unmodified lines
25842624 refreshFileScript(entityID);
25852625 }
25862626 if (isEntityScriptRunning(entityID)) {
2587− EntityScriptDetails details = _entityScripts[entityID];
2627+ EntityScriptDetails details;
2628+ {
2629+ QWriteLocker locker { &_entityScriptsLock };
2630+ details = _entityScripts[entityID];
2631+ }
25882632 QScriptValue entityScript = details.scriptObject; // previously loaded
25892633
25902634 // If this is a remote call, we need to check to see if the function is remotely callable
@@ -2646,7 +2690,11 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 55 unmodified lines
26462690 refreshFileScript(entityID);
26472691 }
26482692 if (isEntityScriptRunning(entityID)) {
2649− EntityScriptDetails details = _entityScripts[entityID];
2693+ EntityScriptDetails details;
2694+ {
2695+ QWriteLocker locker { &_entityScriptsLock };
2696+ details = _entityScripts[entityID];
2697+ }
26502698 QScriptValue entityScript = details.scriptObject; // previously loaded
26512699 if (entityScript.property(methodName).isFunction()) {
26522700 QScriptValueList args;
@@ -2680,7 +2728,11 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 27 unmodified lines
26802728 refreshFileScript(entityID);
26812729 }
26822730 if (isEntityScriptRunning(entityID)) {
2683− EntityScriptDetails details = _entityScripts[entityID];
2731+ EntityScriptDetails details;
2732+ {
2733+ QWriteLocker locker { &_entityScriptsLock };
2734+ details = _entityScripts[entityID];
2735+ }
26842736 QScriptValue entityScript = details.scriptObject; // previously loaded
26852737 if (entityScript.property(methodName).isFunction()) {
26862738 QScriptValueList args;