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 <hjk@qt.io>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Jarek Kobus
2020-12-07 15:19:35 +01:00
parent 43249f655b
commit a0079b171f
5 changed files with 40 additions and 6 deletions

View File

@@ -44,11 +44,12 @@
#include <cplusplus/TypeVisitor.h> #include <cplusplus/TypeVisitor.h>
#include <cplusplus/CoreTypes.h> #include <cplusplus/CoreTypes.h>
#include <QStack>
#include <QByteArray>
#include <QBitArray> #include <QBitArray>
#include <QDir> #include <QByteArray>
#include <QDebug> #include <QDebug>
#include <QDir>
#include <QFutureInterface>
#include <QStack>
/*! /*!
\namespace CPlusPlus \namespace CPlusPlus
@@ -873,9 +874,15 @@ Utils::FilePaths Snapshot::filesDependingOn(const Utils::FilePath &fileName) con
} }
void Snapshot::updateDependencyTable() const void Snapshot::updateDependencyTable() const
{
QFutureInterfaceBase futureInterface;
updateDependencyTable(futureInterface);
}
void Snapshot::updateDependencyTable(QFutureInterfaceBase &futureInterface) const
{ {
if (m_deps.files.isEmpty()) if (m_deps.files.isEmpty())
m_deps.build(*this); m_deps.build(futureInterface, *this);
} }
bool Snapshot::operator==(const Snapshot &other) const bool Snapshot::operator==(const Snapshot &other) const

View File

@@ -39,6 +39,10 @@
#include <QFileInfo> #include <QFileInfo>
#include <QAtomicInt> #include <QAtomicInt>
QT_BEGIN_NAMESPACE
class QFutureInterfaceBase;
QT_END_NAMESPACE
namespace CPlusPlus { namespace CPlusPlus {
class Macro; class Macro;
@@ -443,6 +447,7 @@ public:
Utils::FilePaths filesDependingOn(const QString &fileName) const Utils::FilePaths filesDependingOn(const QString &fileName) const
{ return filesDependingOn(Utils::FilePath::fromString(fileName)); } { return filesDependingOn(Utils::FilePath::fromString(fileName)); }
void updateDependencyTable() const; void updateDependencyTable() const;
void updateDependencyTable(QFutureInterfaceBase &futureInterface) const;
bool operator==(const Snapshot &other) const; bool operator==(const Snapshot &other) const;

View File

@@ -26,6 +26,7 @@
#include "CppDocument.h" #include "CppDocument.h"
#include <QDebug> #include <QDebug>
#include <QFutureInterface>
using namespace CPlusPlus; using namespace CPlusPlus;
@@ -47,13 +48,16 @@ Utils::FilePaths DependencyTable::filesDependingOn(const Utils::FilePath &fileNa
return deps; return deps;
} }
void DependencyTable::build(const Snapshot &snapshot) void DependencyTable::build(QFutureInterfaceBase &futureInterface, const Snapshot &snapshot)
{ {
files.clear(); files.clear();
fileIndex.clear(); fileIndex.clear();
includes.clear(); includes.clear();
includeMap.clear(); includeMap.clear();
if (futureInterface.isCanceled())
return;
const int documentCount = snapshot.size(); const int documentCount = snapshot.size();
files.resize(documentCount); files.resize(documentCount);
includeMap.resize(documentCount); includeMap.resize(documentCount);
@@ -65,6 +69,9 @@ void DependencyTable::build(const Snapshot &snapshot)
fileIndex[it.key()] = i; fileIndex[it.key()] = i;
} }
if (futureInterface.isCanceled())
return;
for (int i = 0; i < files.size(); ++i) { for (int i = 0; i < files.size(); ++i) {
const Utils::FilePath &fileName = files.at(i); const Utils::FilePath &fileName = files.at(i);
if (Document::Ptr doc = snapshot.document(fileName)) { if (Document::Ptr doc = snapshot.document(fileName)) {
@@ -81,10 +88,14 @@ void DependencyTable::build(const Snapshot &snapshot)
directIncludes.append(index); directIncludes.append(index);
bitmap.setBit(index, true); bitmap.setBit(index, true);
if (futureInterface.isCanceled())
return;
} }
includeMap[i] = bitmap; includeMap[i] = bitmap;
includes[i] = directIncludes; includes[i] = directIncludes;
if (futureInterface.isCanceled())
return;
} }
} }
@@ -99,12 +110,18 @@ void DependencyTable::build(const Snapshot &snapshot)
foreach (int includedFileIndex, includes.value(i)) { foreach (int includedFileIndex, includes.value(i)) {
bitmap |= includeMap.value(includedFileIndex); bitmap |= includeMap.value(includedFileIndex);
if (futureInterface.isCanceled())
return;
} }
if (bitmap != previousBitmap) { if (bitmap != previousBitmap) {
includeMap[i] = bitmap; includeMap[i] = bitmap;
changed = true; changed = true;
} }
if (futureInterface.isCanceled())
return;
} }
if (futureInterface.isCanceled())
return;
} while (changed); } while (changed);
} }

View File

@@ -35,6 +35,10 @@
#include <QStringList> #include <QStringList>
#include <QVector> #include <QVector>
QT_BEGIN_NAMESPACE
class QFutureInterfaceBase;
QT_END_NAMESPACE
namespace CPlusPlus { namespace CPlusPlus {
class Snapshot; class Snapshot;
@@ -43,7 +47,7 @@ class CPLUSPLUS_EXPORT DependencyTable
{ {
private: private:
friend class Snapshot; friend class Snapshot;
void build(const Snapshot &snapshot); void build(QFutureInterfaceBase &futureInterface, const Snapshot &snapshot);
Utils::FilePaths filesDependingOn(const Utils::FilePath &fileName) const; Utils::FilePaths filesDependingOn(const Utils::FilePath &fileName) const;
QVector<Utils::FilePath> files; QVector<Utils::FilePath> files;

View File

@@ -213,6 +213,7 @@ void CppClass::lookupDerived(QFutureInterfaceBase &futureInterface,
{ {
using Data = QPair<CppClass*, CppTools::TypeHierarchy>; using Data = QPair<CppClass*, CppTools::TypeHierarchy>;
snapshot.updateDependencyTable(futureInterface);
CppTools::TypeHierarchyBuilder builder(declaration, snapshot); CppTools::TypeHierarchyBuilder builder(declaration, snapshot);
const CppTools::TypeHierarchy &completeHierarchy = builder.buildDerivedTypeHierarchy(futureInterface); const CppTools::TypeHierarchy &completeHierarchy = builder.buildDerivedTypeHierarchy(futureInterface);