From 806d06b5529104c6f41f1748381204c1f4c6b9fc Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 12 May 2016 17:49:47 -0700 Subject: [PATCH] Wait on old entity script engines in threadpool --- .../src/EntityTreeRenderer.cpp | 21 +++++++++++++------ libraries/script-engine/src/ScriptEngine.h | 14 ++++++------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c73a7ae6c7..7643e446ec 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -83,14 +84,22 @@ void EntityTreeRenderer::resetEntitiesScriptEngine() { auto newEngine = new ScriptEngine(NO_SCRIPT, QString("Entities %1").arg(++_entitiesScriptEngineCount)); _entitiesScriptEngine = QSharedPointer(newEngine, [](ScriptEngine* engine){ - // Gracefully exit + class WaitRunnable : public QRunnable { + public: + WaitRunnable(ScriptEngine* engine) : _engine(engine) {} + virtual void run() override { + _engine->wait(); + _engine->deleteLater(); + } + + private: + ScriptEngine* _engine; + }; + engine->unloadAllEntityScripts(); engine->stop(); - - // Disgracefully exit, if necessary - QTimer::singleShot(ScriptEngine::MAX_SCRIPT_EVALUATION_TIME, engine, &ScriptEngine::abort); - - engine->deleteLater(); + // Wait for the scripting thread from the thread pool to avoid hanging the main thread + QThreadPool::globalInstance()->start(new WaitRunnable(engine)); }); _scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine.data()); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index bb4814eb94..b107e741f4 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -83,6 +83,13 @@ public: /// run the script in the callers thread, exit when stop() is called. void run(); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts + Q_INVOKABLE void stop(); + + // Stop any evaluating scripts and wait for the scripting thread to finish. + void wait(); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can // properly ensure they are only called on the correct thread @@ -138,10 +145,6 @@ public: Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts - Q_INVOKABLE void stop(); - bool isFinished() const { return _isFinished; } // used by Application and ScriptWidget bool isRunning() const { return _isRunning; } // used by ScriptWidget @@ -201,9 +204,6 @@ protected: void init(); QString getFilename() const; - // Stop any evaluating scripts and wait for the scripting thread to finish. - void wait(); - bool evaluatePending() const { return _evaluatesPending > 0; } void timerFired(); void stopAllTimers();