diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-11-29 11:21:00 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-11-30 09:33:52 +0100 |
commit | 7035d1bcf8cb3a7f96d2970cd37132b7bc43719f (patch) | |
tree | 759074ce7c612865fbc7d952951b3b14c2f23a11 /src/qmlworkerscript | |
parent | 1cae237329be3badbe75a42d061757ed2345817e (diff) |
WorkerScript: Create ExecutionEngines on demand when needed
Creating an engine is rather expensive and as long as your script
doesn't run, we don't need one. Furthermore, this allows us to create
the engine in the same thread it will run in. Not only is this
stylistically better, but it will also let the engine check its stack
limits correctly on creation (once we do check stack limits).
Task-number: QTBUG-108182
Task-number: QTBUG-106875
Change-Id: Id0003b333c576b3bb603d8b71a5070211c7475bf
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qmlworkerscript')
-rw-r--r-- | src/qmlworkerscript/qquickworkerscript.cpp | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/src/qmlworkerscript/qquickworkerscript.cpp b/src/qmlworkerscript/qquickworkerscript.cpp index 0aa9b936c8..8df631c6d3 100644 --- a/src/qmlworkerscript/qquickworkerscript.cpp +++ b/src/qmlworkerscript/qquickworkerscript.cpp @@ -119,11 +119,16 @@ public: QMutex m_lock; QWaitCondition m_wait; - QHash<int, QV4::ExecutionEngine *> workers; + // ExecutionEngines are owned by the worker script and created and deleted + // in the worker thread. QQuickWorkerScript instances, however, belong to + // the main thread. They are only inserted as place holders when creating + // the worker script. + QHash<int, QBiPointer<QV4::ExecutionEngine, QQuickWorkerScript>> workers; int m_nextId; static QV4::ReturnedValue method_sendMessage(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc); + QV4::ExecutionEngine *workerEngine(int id); signals: void stopThread(); @@ -177,7 +182,8 @@ bool QQuickWorkerScriptEnginePrivate::event(QEvent *event) WorkerRemoveEvent *workerEvent = static_cast<WorkerRemoveEvent *>(event); auto itr = workers.find(workerEvent->workerId()); if (itr != workers.end()) { - delete itr.value(); + if (itr->isT1()) + delete itr->asT1(); workers.erase(itr); } return true; @@ -186,9 +192,26 @@ bool QQuickWorkerScriptEnginePrivate::event(QEvent *event) } } +QV4::ExecutionEngine *QQuickWorkerScriptEnginePrivate::workerEngine(int id) +{ + const auto it = workers.find(id); + if (it == workers.end()) + return nullptr; + if (it->isT1()) + return it->asT1(); + + QQuickWorkerScript *owner = it->asT2(); + auto *engine = new QV4::ExecutionEngine; + WorkerScript *script = workerScriptExtension(engine); + script->owner = owner; + script->p = this; + *it = engine; + return engine; +} + void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &data) { - QV4::ExecutionEngine *engine = workers.value(id); + QV4::ExecutionEngine *engine = workerEngine(id); if (!engine) return; @@ -222,7 +245,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) QString fileName = QQmlFile::urlToLocalFileOrQrc(url); - QV4::ExecutionEngine *engine = workers.value(id); + QV4::ExecutionEngine *engine = workerEngine(id); if (!engine) return; @@ -384,25 +407,25 @@ WorkerScript::WorkerScript(QV4::ExecutionEngine *engine) int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner) { const int id = d->m_nextId++; - auto *engine = new QV4::ExecutionEngine; d->m_lock.lock(); - d->workers.insert(id, engine); + d->workers.insert(id, owner); d->m_lock.unlock(); - WorkerScript *script = workerScriptExtension(engine); - script->owner = owner; - script->p = d; - return id; } void QQuickWorkerScriptEngine::removeWorkerScript(int id) { - if (QV4::ExecutionEngine *engine = d->workers.value(id)) { + const auto it = d->workers.find(id); + if (it == d->workers.end()) + return; + + if (it->isT1()) { + QV4::ExecutionEngine *engine = it->asT1(); workerScriptExtension(engine)->owner = nullptr; - QCoreApplication::postEvent(d, new WorkerRemoveEvent(id)); } + QCoreApplication::postEvent(d, new WorkerRemoveEvent(id)); } void QQuickWorkerScriptEngine::executeUrl(int id, const QUrl &url) @@ -418,14 +441,16 @@ void QQuickWorkerScriptEngine::sendMessage(int id, const QByteArray &data) void QQuickWorkerScriptEngine::run() { d->m_lock.lock(); - d->m_wait.wakeAll(); - d->m_lock.unlock(); exec(); - qDeleteAll(d->workers); + for (auto it = d->workers.begin(), end = d->workers.end(); it != end; ++it) { + if (it->isT1()) + delete it->asT1(); + } + d->workers.clear(); } |