diff options
author | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-10-16 17:21:55 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-11-03 09:00:11 +0000 |
commit | 164af37710e5721cbc7d79a0af20f2387181c59c (patch) | |
tree | 90949e65a650c6f10a968e83e83dbf7574c518b5 /src/qml/qml/qqmltypeloader.cpp | |
parent | 051684f125bbc31bd882c4cd313c3482bcd145a0 (diff) |
Load component synchronously in method_createQmlObject
setData() is not guaranteed to synchronously load the type. In
fact, most of the time, it doesn't. However, by adding a private
Synchronous mode to QQmlTypeLoader we can prefetch the type
synchronously and then inject it into the component.
Task-number: QTBUG-45418
Change-Id: I640f12ad20c01b778b5bc41f43574d8aea504195
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/qml/qml/qqmltypeloader.cpp')
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 149 |
1 files changed, 84 insertions, 65 deletions
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 270c28c399..29f1ca7959 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -911,97 +911,116 @@ void QQmlTypeLoader::unlock() m_thread->unlock(); } -/*! -Load the provided \a blob from the network or filesystem. +struct PlainLoader { + void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const + { + loader->loadThread(blob); + } + void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const + { + loader->m_thread->load(blob); + } + void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const + { + loader->m_thread->loadAsync(blob); + } +}; -The loader must be locked. -*/ -void QQmlTypeLoader::load(QQmlDataBlob *blob, Mode mode) +struct StaticLoader { + const QByteArray &data; + StaticLoader(const QByteArray &data) : data(data) {} + + void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const + { + loader->loadWithStaticDataThread(blob, data); + } + void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const + { + loader->m_thread->loadWithStaticData(blob, data); + } + void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const + { + loader->m_thread->loadWithStaticDataAsync(blob, data); + } +}; + +struct CachedLoader { + const QQmlPrivate::CachedQmlUnit *unit; + CachedLoader(const QQmlPrivate::CachedQmlUnit *unit) : unit(unit) {} + + void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const + { + loader->loadWithCachedUnitThread(blob, unit); + } + void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const + { + loader->m_thread->loadWithCachedUnit(blob, unit); + } + void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const + { + loader->m_thread->loadWithCachedUnit(blob, unit); + } +}; + +template<typename Loader> +void QQmlTypeLoader::doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode) { #ifdef DATABLOB_DEBUG - qWarning("QQmlTypeLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()), + qWarning("QQmlTypeLoader::doLoad(%s): %s thread", qPrintable(blob->m_url.toString()), m_thread->isThisThread()?"Compile":"Engine"); #endif blob->startLoading(); if (m_thread->isThisThread()) { unlock(); - loadThread(blob); + loader.loadThread(this, blob); lock(); - } else if (mode == PreferSynchronous) { + } else if (mode == Asynchronous) { + blob->m_data.setIsAsync(true); unlock(); - m_thread->load(blob); + loader.loadAsync(this, blob); lock(); - if (!blob->isCompleteOrError()) - blob->m_data.setIsAsync(true); } else { - Q_ASSERT(mode == Asynchronous); - blob->m_data.setIsAsync(true); unlock(); - m_thread->loadAsync(blob); + loader.load(this, blob); lock(); + if (mode == PreferSynchronous) { + if (!blob->isCompleteOrError()) + blob->m_data.setIsAsync(true); + } else { + Q_ASSERT(mode == Synchronous); + while (!blob->isCompleteOrError()) { + unlock(); + m_thread->waitForNextMessage(); + lock(); + } + } } } /*! -Load the provided \a blob with \a data. The blob's URL is not used by the data loader in this case. +Load the provided \a blob from the network or filesystem. The loader must be locked. */ -void QQmlTypeLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode) +void QQmlTypeLoader::load(QQmlDataBlob *blob, Mode mode) { -#ifdef DATABLOB_DEBUG - qWarning("QQmlTypeLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()), - m_thread->isThisThread()?"Compile":"Engine"); -#endif + doLoad(PlainLoader(), blob, mode); +} - blob->startLoading(); +/*! +Load the provided \a blob with \a data. The blob's URL is not used by the data loader in this case. - if (m_thread->isThisThread()) { - unlock(); - loadWithStaticDataThread(blob, data); - lock(); - } else if (mode == PreferSynchronous) { - unlock(); - m_thread->loadWithStaticData(blob, data); - lock(); - if (!blob->isCompleteOrError()) - blob->m_data.setIsAsync(true); - } else { - Q_ASSERT(mode == Asynchronous); - blob->m_data.setIsAsync(true); - unlock(); - m_thread->loadWithStaticDataAsync(blob, data); - lock(); - } +The loader must be locked. +*/ +void QQmlTypeLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode) +{ + doLoad(StaticLoader(data), blob, mode); } void QQmlTypeLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode) { -#ifdef DATABLOB_DEBUG - qWarning("QQmlTypeLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()), - m_thread->isThisThread()?"Compile":"Engine"); -#endif - - blob->startLoading(); - - if (m_thread->isThisThread()) { - unlock(); - loadWithCachedUnitThread(blob, unit); - lock(); - } else if (mode == PreferSynchronous) { - unlock(); - m_thread->loadWithCachedUnit(blob, unit); - lock(); - if (!blob->isCompleteOrError()) - blob->m_data.setIsAsync(true); - } else { - Q_ASSERT(mode == Asynchronous); - blob->m_data.setIsAsync(true); - unlock(); - m_thread->loadWithCachedUnitAsync(blob, unit); - lock(); - } + doLoad(CachedLoader(unit), blob, mode); } void QQmlTypeLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data) @@ -1618,7 +1637,7 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode) } else { QQmlTypeLoader::load(typeData, mode); } - } else if ((mode == PreferSynchronous) && QQmlFile::isSynchronous(url)) { + } else if ((mode == PreferSynchronous || mode == Synchronous) && QQmlFile::isSynchronous(url)) { // this was started Asynchronous, but we need to force Synchronous // completion now (if at all possible with this type of URL). @@ -1643,12 +1662,12 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode) Returns a QQmlTypeData for the given \a data with the provided base \a url. The QQmlTypeData will not be cached. */ -QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url) +QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url, Mode mode) { LockHolder<QQmlTypeLoader> holder(this); QQmlTypeData *typeData = new QQmlTypeData(url, this); - QQmlTypeLoader::loadWithStaticData(typeData, data); + QQmlTypeLoader::loadWithStaticData(typeData, data, mode); return typeData; } |