aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.cpp67
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.h5
-rw-r--r--src/libs/qmljs/qmljsplugindumper.cpp13
-rw-r--r--tests/auto/qml/codemodel/check/tst_check.cpp2
-rw-r--r--tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp2
-rw-r--r--tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp5
6 files changed, 34 insertions, 60 deletions
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
index 86e1e7046e9..e89b8ae23c8 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
@@ -106,6 +106,7 @@ ModelManagerInterface::ModelManagerInterface(QObject *parent)
m_defaultImportPaths(environmentImportPaths()),
m_pluginDumper(new PluginDumper(this))
{
+ m_futureSynchronizer.setCancelOnWait(false);
m_indexerDisabled = qEnvironmentVariableIsSet("QTC_NO_CODE_INDEXER");
m_updateCppQmlTypesTimer = new QTimer(this);
@@ -307,20 +308,6 @@ void ModelManagerInterface::updateSourceFiles(const QStringList &files,
refreshSourceFiles(files, emitDocumentOnDiskChanged);
}
-void ModelManagerInterface::cleanupFutures()
-{
- QMutexLocker lock(&m_futuresMutex);
- const int maxFutures = 10;
- if (m_futures.size() > maxFutures) {
- const QList<QFuture<void>> futures = m_futures;
- m_futures.clear();
- for (const QFuture<void> &future : futures) {
- if (!(future.isFinished() || future.isCanceled()))
- m_futures.append(future);
- }
- }
-}
-
QFuture<void> ModelManagerInterface::refreshSourceFiles(const QStringList &sourceFiles,
bool emitDocumentOnDiskChanged)
{
@@ -355,9 +342,9 @@ QFuture<void> ModelManagerInterface::refreshSourceFiles(const QStringList &sourc
void ModelManagerInterface::fileChangedOnDisk(const QString &path)
{
- Utils::runAsync(&ModelManagerInterface::parse,
+ addFuture(Utils::runAsync(&ModelManagerInterface::parse,
workingCopyInternal(), QStringList(path),
- this, Dialect(Dialect::AnyLanguage), true);
+ this, Dialect(Dialect::AnyLanguage), true));
}
void ModelManagerInterface::removeFiles(const QStringList &files)
@@ -654,7 +641,7 @@ QList<ModelManagerInterface::ProjectInfo> ModelManagerInterface::allProjectInfos
bool ModelManagerInterface::isIdle() const
{
- return m_futures.isEmpty();
+ return m_futureSynchronizer.isEmpty();
}
void ModelManagerInterface::emitDocumentChangedOnDisk(Document::Ptr doc)
@@ -1571,41 +1558,37 @@ void ModelManagerInterface::setDefaultVContext(const ViewerContext &vContext)
m_defaultVContexts[vContext.language] = vContext;
}
-void ModelManagerInterface::test_joinAllThreads()
+void ModelManagerInterface::joinAllThreads()
{
- // Loop since futures can spawn more futures as they finish.
while (true) {
- QFuture<void> f;
- // get one future
+ FutureSynchronizer futureSynchronizer;
{
- QMutexLocker lock(&m_futuresMutex);
- for (QFuture<void> &future : m_futures) {
- if (!future.isFinished() && !future.isCanceled()) {
- f = future;
- break;
- }
- }
- }
- if (!f.isFinished() && !f.isCanceled()) {
- f.waitForFinished();
-
- // Some futures trigger more futures from connected signals
- // and in tests, we care about finishing all of these too.
- QEventLoop().processEvents();
- } else {
- break;
+ QMutexLocker locker(&m_futuresMutex);
+ futureSynchronizer = m_futureSynchronizer;
+ m_futureSynchronizer.clearFutures();
}
+ if (futureSynchronizer.isEmpty())
+ return;
}
- m_futures.clear();
}
-void ModelManagerInterface::addFuture(const QFuture<void> &future)
+void ModelManagerInterface::test_joinAllThreads()
{
- {
+ while (true) {
+ joinAllThreads();
+ // In order to process all onFinished handlers of finished futures
+ QCoreApplication::processEvents();
QMutexLocker lock(&m_futuresMutex);
- m_futures.append(future);
+ // If handlers created new futures, repeat the loop
+ if (m_futureSynchronizer.isEmpty())
+ return;
}
- cleanupFutures();
+}
+
+void ModelManagerInterface::addFuture(const QFuture<void> &future)
+{
+ QMutexLocker lock(&m_futuresMutex);
+ m_futureSynchronizer.addFuture(future);
}
Document::Ptr ModelManagerInterface::ensuredGetDocumentForPath(const QString &filePath)
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h
index f6142255469..e31c69b84e4 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.h
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h
@@ -32,6 +32,7 @@
#include <cplusplus/CppDocument.h>
#include <utils/environment.h>
+#include <utils/futuresynchronizer.h>
#include <utils/qrcparser.h>
#include <QFuture>
@@ -243,7 +244,7 @@ protected:
void setDefaultProject(const ProjectInfo &pInfo, ProjectExplorer::Project *p);
private:
- void cleanupFutures();
+ void joinAllThreads();
void iterateQrcFiles(ProjectExplorer::Project *project,
QrcResourceSelector resources,
const std::function<void(Utils::QrcParser::ConstPtr)> &callback);
@@ -280,7 +281,7 @@ private:
PluginDumper *m_pluginDumper = nullptr;
mutable QMutex m_futuresMutex;
- QList<QFuture<void>> m_futures;
+ Utils::FutureSynchronizer m_futureSynchronizer;
bool m_indexerDisabled = false;
};
diff --git a/src/libs/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp
index a98f7550d62..376166559f3 100644
--- a/src/libs/qmljs/qmljsplugindumper.cpp
+++ b/src/libs/qmljs/qmljsplugindumper.cpp
@@ -300,9 +300,10 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
QLatin1String("<dump of ") + libraryPath + QLatin1Char('>'));
future.reportFinished(&infos);
});
+ m_modelManager->addFuture(future);
- auto finalFuture = Utils::onFinished(future, this,
- [this, libraryInfo, privatePlugin, libraryPath] (const QFuture<CppQmlTypesInfo>& future) {
+ Utils::onFinished(future, this, [this, libraryInfo, privatePlugin, libraryPath]
+ (const QFuture<CppQmlTypesInfo>& future) {
CppQmlTypesInfo infos = future.result();
LibraryInfo libInfo = libraryInfo;
@@ -325,7 +326,6 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
m_modelManager->updateLibraryInfo(libraryPath, libInfo);
});
- m_modelManager->addFuture(finalFuture);
} else {
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpDone);
libraryInfo.updateFingerprint();
@@ -395,6 +395,7 @@ QFuture<PluginDumper::QmlTypeDescription> PluginDumper::loadQmlTypeDescription(c
future.reportFinished(&result);
});
+ m_modelManager->addFuture(future);
return future;
}
@@ -598,12 +599,12 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
const QString &libraryPath,
QmlJS::LibraryInfo libraryInfo)
{
- auto future = Utils::onFinished(loadQmlTypeDescription(qmltypesFilePaths), this, [=](const QFuture<PluginDumper::QmlTypeDescription> &typesFuture)
+ Utils::onFinished(loadQmlTypeDescription(qmltypesFilePaths), this, [=](const QFuture<PluginDumper::QmlTypeDescription> &typesFuture)
{
PluginDumper::QmlTypeDescription typesResult = typesFuture.result();
if (!typesResult.dependencies.isEmpty())
{
- auto depFuture = Utils::onFinished(loadDependencies(typesResult.dependencies, QSharedPointer<QSet<QString>>()), this,
+ Utils::onFinished(loadDependencies(typesResult.dependencies, QSharedPointer<QSet<QString>>()), this,
[typesResult, libraryInfo, libraryPath, this] (const QFuture<PluginDumper::DependencyInfo> &loadFuture)
{
PluginDumper::DependencyInfo loadResult = loadFuture.result();
@@ -621,7 +622,6 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
typesResult.moduleApis, objects);
m_modelManager->updateLibraryInfo(libraryPath, libInfo);
});
- m_modelManager->addFuture(depFuture);
} else {
QmlJS::LibraryInfo libInfo = libraryInfo;
prepareLibraryInfo(libInfo, libraryPath, typesResult.dependencies,
@@ -630,7 +630,6 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
m_modelManager->updateLibraryInfo(libraryPath, libInfo);
}
});
- m_modelManager->addFuture(future);
}
void PluginDumper::runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info,
diff --git a/tests/auto/qml/codemodel/check/tst_check.cpp b/tests/auto/qml/codemodel/check/tst_check.cpp
index 35e49392dde..45d3d11880c 100644
--- a/tests/auto/qml/codemodel/check/tst_check.cpp
+++ b/tests/auto/qml/codemodel/check/tst_check.cpp
@@ -101,9 +101,7 @@ void tst_Check::initTestCase()
lPaths.maybeInsert(Utils::FilePath::fromString(p), Dialect::Qml);
ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), lPaths,
modelManager, false);
- QCoreApplication::processEvents();
modelManager->test_joinAllThreads();
- QCoreApplication::processEvents();
}
static bool offsetComparator(const Message &lhs, const Message &rhs)
diff --git a/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp b/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
index 5b6767151f3..e2c5edc6bfd 100644
--- a/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
+++ b/tests/auto/qml/codemodel/dependencies/tst_dependencies.cpp
@@ -151,9 +151,7 @@ void tst_Dependencies::test()
lPaths.maybeInsert(Utils::FilePath::fromString(p), Dialect::Qml);
ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), lPaths,
ModelManagerInterface::instance(), false);
- QCoreApplication::processEvents();
ModelManagerInterface::instance()->test_joinAllThreads();
- QCoreApplication::processEvents();
TestData data = testData(filename);
Document::MutablePtr doc = data.doc;
int nExpectedSemanticMessages = data.semanticMessages;
diff --git a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp
index f325338e4d7..0dc78ecd759 100644
--- a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp
+++ b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp
@@ -76,7 +76,6 @@ void scanDirectory(const QString &dir)
paths.maybeInsert(Utils::FilePath::fromString(dir), Dialect::Qml);
ModelManagerInterface::importScan(result, ModelManagerInterface::workingCopy(), paths,
ModelManagerInterface::instance(), false);
- QCoreApplication::processEvents();
ModelManagerInterface::instance()->test_joinAllThreads();
ViewerContext vCtx;
vCtx.paths.append(dir);
@@ -273,7 +272,6 @@ void tst_ImportCheck::importTypes()
modelManager->activateScan();
modelManager->updateSourceFiles(QStringList(qmlFile), false);
- QCoreApplication::processEvents();
modelManager->test_joinAllThreads();
Snapshot snapshot = modelManager->newestSnapshot();
@@ -288,7 +286,6 @@ void tst_ImportCheck::importTypes()
return link();
};
getContext();
- QCoreApplication::processEvents();
modelManager->test_joinAllThreads();
snapshot = modelManager->newestSnapshot();
doc = snapshot.document(qmlFile);
@@ -367,7 +364,6 @@ void tst_ImportCheck::moduleMapping()
scanDirectory(qtQuickImportPath);
modelManager->updateSourceFiles(QStringList(qmlFile), false);
- QCoreApplication::processEvents();
modelManager->test_joinAllThreads();
Snapshot snapshot = modelManager->newestSnapshot();
@@ -383,7 +379,6 @@ void tst_ImportCheck::moduleMapping()
return link();
};
getContext();
- QCoreApplication::processEvents();
modelManager->test_joinAllThreads();
snapshot = modelManager->newestSnapshot();
doc = snapshot.document(qmlFile);