From a0079b171f98865d34f3e5750b87da8e86968d0a Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 7 Dec 2020 15:19:35 +0100 Subject: [PATCH] Make canceling of Type Hierarchy evaluation more responsive On the beginning of the process of evaluating type hierarchy the evaluating thread may freeze on a first call to Snapshot::updateDependencyTable() for quite a long time (e.g. when showing the type hierarchy for IPlugin class inside Creator project - it may freeze up to about 3 seconds). So, when we want to cancel the evaluation (e.g. when we switch from "Type Hierarchy" into another view or when closing Creator) we may freeze for this period. In order to fix it we pass a future interface as an additional argument for Snapshot::updateDependencyTable() and cancel the update when cancellation of task was requested. Change-Id: I2147f10a68989587476c30369ec2ac552a57d5ae Reviewed-by: hjk Reviewed-by: Christian Kandeler --- src/libs/cplusplus/CppDocument.cpp | 15 +++++++++++---- src/libs/cplusplus/CppDocument.h | 5 +++++ src/libs/cplusplus/DependencyTable.cpp | 19 ++++++++++++++++++- src/libs/cplusplus/DependencyTable.h | 6 +++++- src/plugins/cpptools/cppelementevaluator.cpp | 1 + 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 7df56038372..e33c4708965 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -44,11 +44,12 @@ #include #include -#include -#include #include -#include +#include #include +#include +#include +#include /*! \namespace CPlusPlus @@ -873,9 +874,15 @@ Utils::FilePaths Snapshot::filesDependingOn(const Utils::FilePath &fileName) con } void Snapshot::updateDependencyTable() const +{ + QFutureInterfaceBase futureInterface; + updateDependencyTable(futureInterface); +} + +void Snapshot::updateDependencyTable(QFutureInterfaceBase &futureInterface) const { if (m_deps.files.isEmpty()) - m_deps.build(*this); + m_deps.build(futureInterface, *this); } bool Snapshot::operator==(const Snapshot &other) const diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index 4518b37c9e2..b386f46d54a 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -39,6 +39,10 @@ #include #include +QT_BEGIN_NAMESPACE +class QFutureInterfaceBase; +QT_END_NAMESPACE + namespace CPlusPlus { class Macro; @@ -443,6 +447,7 @@ public: Utils::FilePaths filesDependingOn(const QString &fileName) const { return filesDependingOn(Utils::FilePath::fromString(fileName)); } void updateDependencyTable() const; + void updateDependencyTable(QFutureInterfaceBase &futureInterface) const; bool operator==(const Snapshot &other) const; diff --git a/src/libs/cplusplus/DependencyTable.cpp b/src/libs/cplusplus/DependencyTable.cpp index 4a2b71d053b..2f6b4600f8c 100644 --- a/src/libs/cplusplus/DependencyTable.cpp +++ b/src/libs/cplusplus/DependencyTable.cpp @@ -26,6 +26,7 @@ #include "CppDocument.h" #include +#include using namespace CPlusPlus; @@ -47,13 +48,16 @@ Utils::FilePaths DependencyTable::filesDependingOn(const Utils::FilePath &fileNa return deps; } -void DependencyTable::build(const Snapshot &snapshot) +void DependencyTable::build(QFutureInterfaceBase &futureInterface, const Snapshot &snapshot) { files.clear(); fileIndex.clear(); includes.clear(); includeMap.clear(); + if (futureInterface.isCanceled()) + return; + const int documentCount = snapshot.size(); files.resize(documentCount); includeMap.resize(documentCount); @@ -65,6 +69,9 @@ void DependencyTable::build(const Snapshot &snapshot) fileIndex[it.key()] = i; } + if (futureInterface.isCanceled()) + return; + for (int i = 0; i < files.size(); ++i) { const Utils::FilePath &fileName = files.at(i); if (Document::Ptr doc = snapshot.document(fileName)) { @@ -81,10 +88,14 @@ void DependencyTable::build(const Snapshot &snapshot) directIncludes.append(index); bitmap.setBit(index, true); + if (futureInterface.isCanceled()) + return; } includeMap[i] = bitmap; includes[i] = directIncludes; + if (futureInterface.isCanceled()) + return; } } @@ -99,12 +110,18 @@ void DependencyTable::build(const Snapshot &snapshot) foreach (int includedFileIndex, includes.value(i)) { bitmap |= includeMap.value(includedFileIndex); + if (futureInterface.isCanceled()) + return; } if (bitmap != previousBitmap) { includeMap[i] = bitmap; changed = true; } + if (futureInterface.isCanceled()) + return; } + if (futureInterface.isCanceled()) + return; } while (changed); } diff --git a/src/libs/cplusplus/DependencyTable.h b/src/libs/cplusplus/DependencyTable.h index 8b8851cae50..a2caa1d0b3b 100644 --- a/src/libs/cplusplus/DependencyTable.h +++ b/src/libs/cplusplus/DependencyTable.h @@ -35,6 +35,10 @@ #include #include +QT_BEGIN_NAMESPACE +class QFutureInterfaceBase; +QT_END_NAMESPACE + namespace CPlusPlus { class Snapshot; @@ -43,7 +47,7 @@ class CPLUSPLUS_EXPORT DependencyTable { private: friend class Snapshot; - void build(const Snapshot &snapshot); + void build(QFutureInterfaceBase &futureInterface, const Snapshot &snapshot); Utils::FilePaths filesDependingOn(const Utils::FilePath &fileName) const; QVector files; diff --git a/src/plugins/cpptools/cppelementevaluator.cpp b/src/plugins/cpptools/cppelementevaluator.cpp index 2d9275ba595..208f75433dc 100644 --- a/src/plugins/cpptools/cppelementevaluator.cpp +++ b/src/plugins/cpptools/cppelementevaluator.cpp @@ -213,6 +213,7 @@ void CppClass::lookupDerived(QFutureInterfaceBase &futureInterface, { using Data = QPair; + snapshot.updateDependencyTable(futureInterface); CppTools::TypeHierarchyBuilder builder(declaration, snapshot); const CppTools::TypeHierarchy &completeHierarchy = builder.buildDerivedTypeHierarchy(futureInterface);