History

more work on proper threading of ScriptEngine

Brad Hefta-Gaub committed 11 years ago

Commit a3c02881 parent 18fbf896 files · +151 −116Browse files

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

Unified · Split

libraries/script-engine/src/ScriptEngine.cpp+128−65
@@ -222,7 +222,7 @@ QString ScriptEngine::getFilename() const { · 221 unmodified lines
222222 }
223223
224224
225−// FIXME - remove the file/url scheme code here and let the script cache handle things
225+// FIXME - switch this to the new model of ScriptCache callbacks
226226 void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) {
227227 if (_isRunning) {
228228 return;
@@ -238,6 +238,7 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) { · 9 unmodified lines
238238 scriptCache->getScript(url, this, isPending, reload);
239239 }
240240
241+// FIXME - switch this to the new model of ScriptCache callbacks
241242 void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scriptContents) {
242243 _scriptContents = scriptContents;
243244 if (_wantSignals) {
@@ -245,6 +246,7 @@ void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scrip · 1 unmodified line
245246 }
246247 }
247248
249+// FIXME - switch this to the new model of ScriptCache callbacks
248250 void ScriptEngine::errorInLoadingScript(const QUrl& url) {
249251 qCDebug(scriptengine) << "ERROR Loading file:" << url.toString() << "line:" << __LINE__;
250252 if (_wantSignals) {
@@ -320,13 +322,17 @@ void ScriptEngine::init() { · 69 unmodified lines
320322
321323 void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) {
322324 if (QThread::currentThread() != thread()) {
325+ #ifdef THREAD_DEBUGGING
323326 qDebug() << "*** WARNING *** ScriptEngine::registerGlobalObject() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;
327+ #endif
324328 QMetaObject::invokeMethod(this, "registerGlobalObject",
325329 Q_ARG(const QString&, name),
326330 Q_ARG(QObject*, object));
327331 return;
328332 }
329− //qDebug() << "ScriptEngine::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name;
333+ #ifdef THREAD_DEBUGGING
334+ qDebug() << "ScriptEngine::registerGlobalObject() called on thread [" << QThread::currentThread() << "] name:" << name;
335+ #endif
330336
331337 if (object) {
332338 QScriptValue value = newQObject(object);
@@ -336,14 +342,18 @@ void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) { · 3 unmodified lines
336342
337343 void ScriptEngine::registerFunction(const QString& name, QScriptEngine::FunctionSignature functionSignature, int numArguments) {
338344 if (QThread::currentThread() != thread()) {
345+ #ifdef THREAD_DEBUGGING
339346 qDebug() << "*** WARNING *** ScriptEngine::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;
347+ #endif
340348 QMetaObject::invokeMethod(this, "registerFunction",
341349 Q_ARG(const QString&, name),
342350 Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
343351 Q_ARG(int, numArguments));
344352 return;
345353 }
346− //qDebug() << "ScriptEngine::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name;
354+ #ifdef THREAD_DEBUGGING
355+ qDebug() << "ScriptEngine::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name;
356+ #endif
347357
348358 QScriptValue scriptFun = newFunction(functionSignature, numArguments);
349359 globalObject().setProperty(name, scriptFun);
@@ -351,14 +361,18 @@ void ScriptEngine::registerFunction(const QString& name, QScriptEngine::Function · 1 unmodified line
351361
352362 void ScriptEngine::registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature functionSignature, int numArguments) {
353363 if (QThread::currentThread() != thread()) {
364+ #ifdef THREAD_DEBUGGING
354365 qDebug() << "*** WARNING *** ScriptEngine::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] parent:" << parent << "name:" << name;
366+ #endif
355367 QMetaObject::invokeMethod(this, "registerFunction",
356368 Q_ARG(const QString&, name),
357369 Q_ARG(QScriptEngine::FunctionSignature, functionSignature),
358370 Q_ARG(int, numArguments));
359371 return;
360372 }
361− //qDebug() << "ScriptEngine::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name;
373+ #ifdef THREAD_DEBUGGING
374+ qDebug() << "ScriptEngine::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name;
375+ #endif
362376
363377 QScriptValue object = globalObject().property(parent);
364378 if (object.isValid()) {
@@ -370,8 +384,10 @@ void ScriptEngine::registerFunction(const QString& parent, const QString& name, · 5 unmodified lines
370384 void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
371385 QScriptEngine::FunctionSignature setter, const QString& parent) {
372386 if (QThread::currentThread() != thread()) {
387+ #ifdef THREAD_DEBUGGING
373388 qDebug() << "*** WARNING *** ScriptEngine::registerGetterSetter() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
374389 " name:" << name << "parent:" << parent;
390+ #endif
375391 QMetaObject::invokeMethod(this, "registerGetterSetter",
376392 Q_ARG(const QString&, name),
377393 Q_ARG(QScriptEngine::FunctionSignature, getter),
@@ -379,7 +395,9 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func · 1 unmodified line
379395 Q_ARG(const QString&, parent));
380396 return;
381397 }
382− //qDebug() << "ScriptEngine::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent;
398+ #ifdef THREAD_DEBUGGING
399+ qDebug() << "ScriptEngine::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent;
400+ #endif
383401
384402 QScriptValue setterFunction = newFunction(setter, 1);
385403 QScriptValue getterFunction = newFunction(getter);
@@ -399,15 +417,19 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func · 13 unmodified lines
399417 // Unregister the handlers for this eventName and entityID.
400418 void ScriptEngine::removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {
401419 if (QThread::currentThread() != thread()) {
420+ #ifdef THREAD_DEBUGGING
402421 qDebug() << "*** WARNING *** ScriptEngine::removeEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
403422 "entityID:" << entityID << " eventName:" << eventName;
423+ #endif
404424 QMetaObject::invokeMethod(this, "removeEventHandler",
405425 Q_ARG(const EntityItemID&, entityID),
406426 Q_ARG(const QString&, eventName),
407427 Q_ARG(QScriptValue, handler));
408428 return;
409429 }
410− //qDebug() << "ScriptEngine::removeEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName;
430+ #ifdef THREAD_DEBUGGING
431+ qDebug() << "ScriptEngine::removeEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName;
432+ #endif
411433
412434 if (!_registeredHandlers.contains(entityID)) {
413435 return;
@@ -425,15 +447,20 @@ void ScriptEngine::removeEventHandler(const EntityItemID& entityID, const QStrin · 11 unmodified lines
425447 // Register the handler.
426448 void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {
427449 if (QThread::currentThread() != thread()) {
450+ #ifdef THREAD_DEBUGGING
428451 qDebug() << "*** WARNING *** ScriptEngine::addEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
429452 "entityID:" << entityID << " eventName:" << eventName;
453+ #endif
454+
430455 QMetaObject::invokeMethod(this, "addEventHandler",
431456 Q_ARG(const EntityItemID&, entityID),
432457 Q_ARG(const QString&, eventName),
433458 Q_ARG(QScriptValue, handler));
434459 return;
435460 }
436− //qDebug() << "ScriptEngine::addEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName;
461+ #ifdef THREAD_DEBUGGING
462+ qDebug() << "ScriptEngine::addEventHandler() called on thread [" << QThread::currentThread() << "] entityID:" << entityID << " eventName : " << eventName;
463+ #endif
437464
438465 if (_registeredHandlers.count() == 0) { // First time any per-entity handler has been added in this script...
439466 // Connect up ALL the handlers to the global entities object's signals.
@@ -496,8 +523,10 @@ QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileN · 56 unmodified lines
496523
497524 if (QThread::currentThread() != thread()) {
498525 QScriptValue result;
526+ #ifdef THREAD_DEBUGGING
499527 qDebug() << "*** WARNING *** ScriptEngine::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
500528 "program:" << program << " fileName:" << fileName << "lineNumber:" << lineNumber;
529+ #endif
501530 QMetaObject::invokeMethod(this, "evaluate", Qt::BlockingQueuedConnection,
502531 Q_RETURN_ARG(QScriptValue, result),
503532 Q_ARG(const QString&, program),
@@ -854,10 +883,10 @@ void ScriptEngine::generalHandler(const EntityItemID& entityID, const QString& e · 350 unmodified lines
854883 // for the download
855884 void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload) {
856885 if (QThread::currentThread() != thread()) {
886+ #ifdef THREAD_DEBUGGING
857887 qDebug() << "*** WARNING *** ScriptEngine::loadEntityScript() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
858− "entityID:" << entityID <<
859− "entityScript:" << entityScript <<
860− "forceRedownload:" << forceRedownload;
888+ "entityID:" << entityID << "entityScript:" << entityScript <<"forceRedownload:" << forceRedownload;
889+ #endif
861890
862891 QMetaObject::invokeMethod(this, "loadEntityScript",
863892 Q_ARG(const EntityItemID&, entityID),
@@ -865,71 +894,104 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& · 1 unmodified line
865894 Q_ARG(bool, forceRedownload));
866895 return;
867896 }
897+ #ifdef THREAD_DEBUGGING
868898 qDebug() << "ScriptEngine::loadEntityScript() called on correct thread [" << thread() << "] "
869− "entityID:" << entityID <<
870− "entityScript:" << entityScript <<
871− "forceRedownload:" << forceRedownload;
899+ "entityID:" << entityID << "entityScript:" << entityScript << "forceRedownload:" << forceRedownload;
900+ #endif
872901
873902 // If we've been called our known entityScripts should not know about us..
874903 assert(!_entityScripts.contains(entityID));
875904
876− auto scriptCache = DependencyManager::get<ScriptCache>();
905+ #ifdef THREAD_DEBUGGING
906+ qDebug() << "ScriptEngine::loadEntityScript() calling scriptCache->getScriptContents() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";
907+ #endif
908+ DependencyManager::get<ScriptCache>()->getScriptContents(entityScript, [=](const QString& scriptOrURL, const QString& contents, bool isURL, bool success) {
909+ #ifdef THREAD_DEBUGGING
910+ qDebug() << "ScriptEngine::entityScriptContentAvailable() IN LAMBDA contentAvailable on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";
911+ #endif
877912
878− scriptCache->getScriptContents(entityScript, [=](const QString& scriptOrURL, const QString& contents, bool isURL, bool success) {
913+ this->entityScriptContentAvailable(entityID, scriptOrURL, contents, isURL, success);
914+ }, forceRedownload);
915+}
879916
880− // first check the syntax of the script contents
881− QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(contents);
882− if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) {
883− qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID;
884− qCDebug(scriptengine) << " " << syntaxCheck.errorMessage() << ":"
885− << syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber();
886− qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
887− scriptCache->addScriptToBadScriptList(scriptOrURL);
888− return; // done processing script
889− }
917+// since all of these operations can be asynch we will always do the actual work in the response handler
918+// for the download
919+void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success) {
920+ if (QThread::currentThread() != thread()) {
921+ #ifdef THREAD_DEBUGGING
922+ qDebug() << "*** WARNING *** ScriptEngine::entityScriptContentAvailable() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
923+ "entityID:" << entityID << "scriptOrURL:" << scriptOrURL << "contents:" << contents << "isURL:" << isURL << "success:" << success;
924+ #endif
890925
891− if (isURL) {
892− setParentURL(scriptOrURL);
893− }
926+ QMetaObject::invokeMethod(this, "entityScriptContentAvailable",
927+ Q_ARG(const EntityItemID&, entityID),
928+ Q_ARG(const QString&, scriptOrURL),
929+ Q_ARG(const QString&, contents),
930+ Q_ARG(bool, isURL),
931+ Q_ARG(bool, success));
932+ return;
933+ }
894934
895− QScriptEngine sandbox;
896− QScriptValue testConstructor = sandbox.evaluate(contents);
935+ #ifdef THREAD_DEBUGGING
936+ qDebug() << "ScriptEngine::entityScriptContentAvailable() thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";
937+ #endif
897938
898− if (!testConstructor.isFunction()) {
899− qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID;
900− qCDebug(scriptengine) << " NOT CONSTRUCTOR";
901− qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
902− scriptCache->addScriptToBadScriptList(scriptOrURL);
903− return; // done processing script
904− }
939+ auto scriptCache = DependencyManager::get<ScriptCache>();
905940
906− QScriptValue entityScriptConstructor = evaluate(contents);
941+ // first check the syntax of the script contents
942+ QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(contents);
943+ if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) {
944+ qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID;
945+ qCDebug(scriptengine) << " " << syntaxCheck.errorMessage() << ":"
946+ << syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber();
947+ qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
948+ scriptCache->addScriptToBadScriptList(scriptOrURL);
949+ return; // done processing script
950+ }
907951
908− QScriptValue entityScriptObject = entityScriptConstructor.construct();
909− EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject };
910− _entityScripts[entityID] = newDetails;
952+ if (isURL) {
953+ setParentURL(scriptOrURL);
954+ }
911955
912− if (isURL) {
913− setParentURL("");
914− }
956+ QScriptEngine sandbox;
957+ QScriptValue testConstructor = sandbox.evaluate(contents);
915958
916− // if we got this far, then call the preload method
917− callEntityScriptMethod(entityID, "preload");
959+ if (!testConstructor.isFunction()) {
960+ qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID;
961+ qCDebug(scriptengine) << " NOT CONSTRUCTOR";
962+ qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
963+ scriptCache->addScriptToBadScriptList(scriptOrURL);
964+ return; // done processing script
965+ }
966+
967+ QScriptValue entityScriptConstructor = evaluate(contents);
918968
919− }, forceRedownload);
969+ QScriptValue entityScriptObject = entityScriptConstructor.construct();
970+ EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject };
971+ _entityScripts[entityID] = newDetails;
972+ if (isURL) {
973+ setParentURL("");
974+ }
975+
976+ // if we got this far, then call the preload method
977+ callEntityScriptMethod(entityID, "preload");
920978 }
921979
922980 void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) {
923981 if (QThread::currentThread() != thread()) {
982+ #ifdef THREAD_DEBUGGING
924983 qDebug() << "*** WARNING *** ScriptEngine::unloadEntityScript() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
925984 "entityID:" << entityID;
985+ #endif
926986
927987 QMetaObject::invokeMethod(this, "unloadEntityScript",
928988 Q_ARG(const EntityItemID&, entityID));
929989 return;
930990 }
991+ #ifdef THREAD_DEBUGGING
931992 qDebug() << "ScriptEngine::unloadEntityScript() called on correct thread [" << thread() << "] "
932993 "entityID:" << entityID;
994+ #endif
933995
934996 if (_entityScripts.contains(entityID)) {
935997 callEntityScriptMethod(entityID, "unload");
@@ -939,18 +1001,20 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { · 3 unmodified lines
9391001
9401002 void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) {
9411003 if (QThread::currentThread() != thread()) {
1004+ #ifdef THREAD_DEBUGGING
9421005 qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
943− "entityID:" << entityID <<
944− "methodName:" << methodName;
1006+ "entityID:" << entityID << "methodName:" << methodName;
1007+ #endif
9451008
9461009 QMetaObject::invokeMethod(this, "callEntityScriptMethod",
9471010 Q_ARG(const EntityItemID&, entityID),
9481011 Q_ARG(const QString&, methodName));
9491012 return;
9501013 }
1014+ #ifdef THREAD_DEBUGGING
9511015 qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] "
952− "entityID:" << entityID <<
953− "methodName:" << methodName;
1016+ "entityID:" << entityID << "methodName:" << methodName;
1017+ #endif
9541018
9551019 if (_entityScripts.contains(entityID)) {
9561020 EntityScriptDetails details = _entityScripts[entityID];
@@ -960,15 +1024,16 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 3 unmodified lines
9601024 args << entityID.toScriptValue(this);
9611025 entityScript.property(methodName).call(entityScript, args);
9621026 }
1027+
9631028 }
9641029 }
9651030
9661031 void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const MouseEvent& event) {
9671032 if (QThread::currentThread() != thread()) {
1033+ #ifdef THREAD_DEBUGGING
9681034 qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
969− "entityID:" << entityID <<
970− "methodName:" << methodName <<
971− "event: mouseEvent";
1035+ "entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";
1036+ #endif
9721037
9731038 QMetaObject::invokeMethod(this, "callEntityScriptMethod",
9741039 Q_ARG(const EntityItemID&, entityID),
@@ -976,10 +1041,10 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 1 unmodified line
9761041 Q_ARG(const MouseEvent&, event));
9771042 return;
9781043 }
1044+ #ifdef THREAD_DEBUGGING
9791045 qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] "
980− "entityID:" << entityID <<
981− "methodName:" << methodName <<
982− "event: mouseEvent";
1046+ "entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";
1047+ #endif
9831048
9841049 if (_entityScripts.contains(entityID)) {
9851050 EntityScriptDetails details = _entityScripts[entityID];
@@ -996,11 +1061,10 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 10 unmodified lines
9961061
9971062 void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision) {
9981063 if (QThread::currentThread() != thread()) {
1064+ #ifdef THREAD_DEBUGGING
9991065 qDebug() << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
1000− "entityID:" << entityID <<
1001− "methodName:" << methodName <<
1002− "otherID:" << otherID <<
1003− "collision: collision";
1066+ "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
1067+ #endif
10041068
10051069 QMetaObject::invokeMethod(this, "callEntityScriptMethod",
10061070 Q_ARG(const EntityItemID&, entityID),
@@ -1009,11 +1073,10 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS · 2 unmodified lines
10091073 Q_ARG(const Collision&, collision));
10101074 return;
10111075 }
1076+ #ifdef THREAD_DEBUGGING
10121077 qDebug() << "ScriptEngine::callEntityScriptMethod() called on correct thread [" << thread() << "] "
1013− "entityID:" << entityID <<
1014− "methodName:" << methodName <<
1015− "otherID:" << otherID <<
1016− "collision: collision";
1078+ "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
1079+ #endif
10171080
10181081 if (_entityScripts.contains(entityID)) {
10191082 EntityScriptDetails details = _entityScripts[entityID];