diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2014-02-06 16:33:15 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-07 12:44:10 +0100 |
commit | 324ae0d7d99ef9f7159d29b2e0e7eabe5f8a43a4 (patch) | |
tree | 9576687c7580065e819392a3be6250dcf6e0c07c /src/qml | |
parent | 50ce88a53107f97664d928719c1877b8077e9a2e (diff) |
[new compiler] Allow for interruption during object finalization
The object tree construction and binding allocation remains synchronous, but
the initial evaluation of the bindings is now cooperatively interruptible
again, like in the VME.
Change-Id: Idd037dd481782c81ad43e20e93d922eb12ac8b85
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlincubator.cpp | 14 | ||||
-rw-r--r-- | src/qml/qml/qqmlincubator_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 19 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlvme.cpp | 8 | ||||
-rw-r--r-- | src/qml/qml/qqmlvme_p.h | 52 |
7 files changed, 50 insertions, 53 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index bf87a9dd2d..cc7ea57602 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -914,7 +914,8 @@ void QQmlComponentPrivate::complete(QQmlEnginePrivate *enginePriv, ConstructionS { if (state->completePending) { if (enginePriv->useNewCompiler) { - state->creator->finalize(); + QQmlInstantiationInterrupt interrupt; + state->creator->finalize(interrupt); } else { state->vme.complete(); } diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index 10fd05ab58..de8eab7bd2 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -91,7 +91,7 @@ void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext) p->changeStatus(QQmlIncubator::Loading); if (!watcher.hasRecursed()) { - QQmlVME::Interrupt i; + QQmlInstantiationInterrupt i; p->incubate(i); } } else { @@ -254,7 +254,7 @@ void QQmlIncubationController::incubatingObjectCountChanged(int incubatingObject Q_UNUSED(incubatingObjectCount); } -void QQmlIncubatorPrivate::forceCompletion(QQmlVME::Interrupt &i) +void QQmlIncubatorPrivate::forceCompletion(QQmlInstantiationInterrupt &i) { while (QQmlIncubator::Loading == status) { while (QQmlIncubator::Loading == status && !waitingFor.isEmpty()) @@ -264,7 +264,7 @@ void QQmlIncubatorPrivate::forceCompletion(QQmlVME::Interrupt &i) } } -void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i) +void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i) { if (!compiledData) return; @@ -345,7 +345,7 @@ void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i) QQmlContextData *ctxt = 0; if (enginePriv->useNewCompiler) - ctxt = creator->finalize(); + ctxt = creator->finalize(i); else ctxt = vme.complete(i); if (ctxt) { @@ -391,7 +391,7 @@ void QQmlIncubationController::incubateFor(int msecs) if (!d || !d->incubatorCount) return; - QQmlVME::Interrupt i(msecs * 1000000); + QQmlInstantiationInterrupt i(msecs * 1000000); i.reset(); do { static_cast<QQmlIncubatorPrivate*>(d->incubatorList.first())->incubate(i); @@ -410,7 +410,7 @@ void QQmlIncubationController::incubateWhile(volatile bool *flag, int msecs) if (!d || !d->incubatorCount) return; - QQmlVME::Interrupt i(flag, msecs * 1000000); + QQmlInstantiationInterrupt i(flag, msecs * 1000000); i.reset(); do { static_cast<QQmlIncubatorPrivate*>(d->incubatorList.first())->incubate(i); @@ -609,7 +609,7 @@ returns, the incubator will not be in the Loading state. */ void QQmlIncubator::forceCompletion() { - QQmlVME::Interrupt i; + QQmlInstantiationInterrupt i; d->forceCompletion(i); } diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h index a8b549bd28..b7009bfe43 100644 --- a/src/qml/qml/qqmlincubator_p.h +++ b/src/qml/qml/qqmlincubator_p.h @@ -104,8 +104,8 @@ public: void clear(); - void forceCompletion(QQmlVME::Interrupt &i); - void incubate(QQmlVME::Interrupt &i); + void forceCompletion(QQmlInstantiationInterrupt &i); + void incubate(QQmlInstantiationInterrupt &i); }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 2b69955dde..faeb3753ea 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1048,13 +1048,16 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent) return result ? instance : 0; } -QQmlContextData *QmlObjectCreator::finalize() +QQmlContextData *QmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt) { { QQmlTrace trace("VME Binding Enable"); trace.event("begin binding eval"); while (!allCreatedBindings->isEmpty()) { + if (interrupt.shouldInterrupt()) + return 0; + QQmlAbstractBinding *b = allCreatedBindings->pop(); if (!b) continue; @@ -1077,10 +1080,8 @@ QQmlContextData *QmlObjectCreator::finalize() status->componentComplete(); } - #if 0 // ### - if (watcher.hasRecursed() || interrupt.shouldInterrupt()) - return 0; - #endif + if (interrupt.shouldInterrupt()) + return 0; } } @@ -1093,10 +1094,6 @@ QQmlContextData *QmlObjectCreator::finalize() void *args[] = { 0 }; QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args); } -#if 0 // ### - if (watcher.hasRecursed()) - return 0; -#endif } finalizeCallbacks.clear(); } @@ -1113,10 +1110,8 @@ QQmlContextData *QmlObjectCreator::finalize() // ### designer if (componentCompleteEnabled()) emit a->completed(); -#if 0 // ### - if (watcher.hasRecursed() || interrupt.shouldInterrupt()) + if (interrupt.shouldInterrupt()) return 0; -#endif } } diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index cb23f61c84..7ed75670c2 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE class QQmlAbstractBinding; struct QQmlTypeCompiler; +class QQmlInstantiationInterrupt; class QmlObjectCreator { @@ -62,7 +63,7 @@ public: ~QmlObjectCreator(); QObject *create(int subComponentIndex = -1, QObject *parent = 0); - QQmlContextData *finalize(); + QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt); QQmlComponentAttached *componentAttached; QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks; diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 58d656a846..7d521192ad 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -184,7 +184,7 @@ struct ActiveVMERestorer }; } -QObject *QQmlVME::execute(QList<QQmlError> *errors, const Interrupt &interrupt) +QObject *QQmlVME::execute(QList<QQmlError> *errors, const QQmlInstantiationInterrupt &interrupt) { Q_ASSERT(states.count() >= 1); @@ -330,7 +330,7 @@ static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::Executi removeBindingOnProperty(o, index) QObject *QQmlVME::run(QList<QQmlError> *errors, - const Interrupt &interrupt + const QQmlInstantiationInterrupt &interrupt #ifdef QML_THREADED_VME_INTERPRETER , void * const **storeJumpTable #endif @@ -1134,14 +1134,14 @@ void *const *QQmlVME::instructionJumpTable() static void * const *jumpTable = 0; if (!jumpTable) { QQmlVME dummy; - QQmlVME::Interrupt i; + QQmlInstantiationInterrupt i; dummy.run(0, i, &jumpTable); } return jumpTable; } #endif -QQmlContextData *QQmlVME::complete(const Interrupt &interrupt) +QQmlContextData *QQmlVME::complete(const QQmlInstantiationInterrupt &interrupt) { Q_ASSERT(engine || (bindValues.isEmpty() && diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h index d26812a68f..5025653524 100644 --- a/src/qml/qml/qqmlvme_p.h +++ b/src/qml/qml/qqmlvme_p.h @@ -102,28 +102,28 @@ Q_DECLARE_TYPEINFO(QQmlVMETypes::List, Q_PRIMITIVE_TYPE | Q_MOVABLE_TYPE); template<> class QTypeInfo<QQmlVMETypes::State> : public QTypeInfoMerger<QQmlVMETypes::State, QBitField> {}; //Q_DECLARE_TYPEINFO +class QQmlInstantiationInterrupt { +public: + inline QQmlInstantiationInterrupt(); + inline QQmlInstantiationInterrupt(volatile bool *runWhile, int nsecs=0); + inline QQmlInstantiationInterrupt(int nsecs); + + inline void reset(); + inline bool shouldInterrupt() const; +private: + enum Mode { None, Time, Flag }; + Mode mode; + struct { + QElapsedTimer timer; + int nsecs; + }; + volatile bool *runWhile; +}; + class Q_QML_PRIVATE_EXPORT QQmlVME { Q_DECLARE_TR_FUNCTIONS(QQmlVME) public: - class Interrupt { - public: - inline Interrupt(); - inline Interrupt(volatile bool *runWhile, int nsecs=0); - inline Interrupt(int nsecs); - - inline void reset(); - inline bool shouldInterrupt() const; - private: - enum Mode { None, Time, Flag }; - Mode mode; - struct { - QElapsedTimer timer; - int nsecs; - }; - volatile bool *runWhile; - }; - QQmlVME() : data(0), componentAttached(0) {} QQmlVME(void *data) : data(data), componentAttached(0) {} @@ -136,8 +136,8 @@ public: bool initDeferred(QObject *); void reset(); - QObject *execute(QList<QQmlError> *errors, const Interrupt & = Interrupt()); - QQmlContextData *complete(const Interrupt & = Interrupt()); + QObject *execute(QList<QQmlError> *errors, const QQmlInstantiationInterrupt & = QQmlInstantiationInterrupt()); + QQmlContextData *complete(const QQmlInstantiationInterrupt & = QQmlInstantiationInterrupt()); static void enableComponentComplete(); static void disableComponentComplete(); @@ -146,7 +146,7 @@ public: private: friend class QQmlVMEGuard; - QObject *run(QList<QQmlError> *errors, const Interrupt & + QObject *run(QList<QQmlError> *errors, const QQmlInstantiationInterrupt & #ifdef QML_THREADED_VME_INTERPRETER , void *const**storeJumpTable = 0 #endif @@ -207,28 +207,28 @@ private: QQmlGuardedContextData *m_contexts; }; -QQmlVME::Interrupt::Interrupt() +QQmlInstantiationInterrupt::QQmlInstantiationInterrupt() : mode(None), nsecs(0), runWhile(0) { } -QQmlVME::Interrupt::Interrupt(volatile bool *runWhile, int nsecs) +QQmlInstantiationInterrupt::QQmlInstantiationInterrupt(volatile bool *runWhile, int nsecs) : mode(Flag), nsecs(nsecs), runWhile(runWhile) { } -QQmlVME::Interrupt::Interrupt(int nsecs) +QQmlInstantiationInterrupt::QQmlInstantiationInterrupt(int nsecs) : mode(Time), nsecs(nsecs), runWhile(0) { } -void QQmlVME::Interrupt::reset() +void QQmlInstantiationInterrupt::reset() { if (mode == Time || nsecs) timer.start(); } -bool QQmlVME::Interrupt::shouldInterrupt() const +bool QQmlInstantiationInterrupt::shouldInterrupt() const { if (mode == None) { return false; |