aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcus Tillmanns <marcus.tillmanns@qt.io>2023-11-09 07:22:47 +0100
committerMarcus Tillmanns <marcus.tillmanns@qt.io>2023-12-14 14:19:31 +0000
commit21c868604eee1e0b26142ce6a4add9bd5c349243 (patch)
treee5867076b1c4d767f933b1ab0c57c4768d0be572
parent3208dc92d36c6e2f91f138c1ca000e4d0fc3f848 (diff)
CppEditor: Use Utils::SynchronizedValue for project data
Change-Id: I67c07c2f5f5f7e8bb6b10d4f492ad062f82977be Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--src/plugins/cppeditor/cppmodelmanager.cpp224
-rw-r--r--src/plugins/cppeditor/cppmodelmanager.h6
2 files changed, 126 insertions, 104 deletions
diff --git a/src/plugins/cppeditor/cppmodelmanager.cpp b/src/plugins/cppeditor/cppmodelmanager.cpp
index 78917eee7c..e754035d51 100644
--- a/src/plugins/cppeditor/cppmodelmanager.cpp
+++ b/src/plugins/cppeditor/cppmodelmanager.cpp
@@ -69,6 +69,7 @@
#include <utils/process.h>
#include <utils/qtcassert.h>
#include <utils/savefile.h>
+#include <utils/synchronizedvalue.h>
#include <utils/temporarydirectory.h>
#include <QAction>
@@ -169,16 +170,20 @@ public:
Snapshot m_snapshot;
// Project integration
- QReadWriteLock m_projectLock;
- QHash<Project *, ProjectData> m_projectData;
- QMap<FilePath, QList<ProjectPart::ConstPtr> > m_fileToProjectParts;
- QMap<QString, ProjectPart::ConstPtr> m_projectPartIdToProjectProjectPart;
+ struct SyncedProjectData
+ {
+ QHash<Project *, ProjectData> m_projectData;
+ QMap<FilePath, QList<ProjectPart::ConstPtr>> m_fileToProjectParts;
+ QMap<QString, ProjectPart::ConstPtr> m_projectPartIdToProjectProjectPart;
+
+ // The members below are cached/(re)calculated from the projects and/or their project parts
+ bool m_dirty{true};
+ FilePaths m_projectFiles;
+ HeaderPaths m_headerPaths;
+ Macros m_definedMacros;
+ };
- // The members below are cached/(re)calculated from the projects and/or their project parts
- bool m_dirty;
- FilePaths m_projectFiles;
- HeaderPaths m_headerPaths;
- Macros m_definedMacros;
+ Utils::SynchronizedValue<SyncedProjectData> m_lockedProjectData;
// Editor integration
mutable QMutex m_cppEditorDocumentsMutex;
@@ -215,6 +220,12 @@ public:
std::unique_ptr<ILocatorFilter> m_currentDocumentFilter;
QList<Document::DiagnosticMessage> m_diagnosticMessages;
+
+ static void recalculateProjectPartMappings(SyncedProjectData &ld);
+ static void ensureUpdated(SyncedProjectData &ld);
+ static Utils::FilePaths internalProjectFiles(SyncedProjectData &ld);
+ static ProjectExplorer::HeaderPaths internalHeaderPaths(SyncedProjectData &ld);
+ static ProjectExplorer::Macros internalDefinedMacros(SyncedProjectData &ld);
};
static CppModelManagerPrivate *d;
@@ -989,8 +1000,6 @@ CppModelManager::CppModelManager()
d->m_findReferences = new CppFindReferences(this);
d->m_indexerEnabled = qtcEnvironmentVariable("QTC_NO_CODE_INDEXER") != "1";
- d->m_dirty = true;
-
d->m_delayedGcTimer.setObjectName(QLatin1String("CppModelManager::m_delayedGcTimer"));
d->m_delayedGcTimer.setSingleShot(true);
connect(&d->m_delayedGcTimer, &QTimer::timeout, this, &CppModelManager::GC);
@@ -1071,22 +1080,21 @@ bool CppModelManager::replaceDocument(Document::Ptr newDoc)
return true;
}
-/// Make sure that m_projectLock is locked for writing when calling this.
-void CppModelManager::ensureUpdated()
+void CppModelManagerPrivate::ensureUpdated(SyncedProjectData &ld)
{
- if (!d->m_dirty)
+ if (!ld.m_dirty)
return;
- d->m_projectFiles = internalProjectFiles();
- d->m_headerPaths = internalHeaderPaths();
- d->m_definedMacros = internalDefinedMacros();
- d->m_dirty = false;
+ ld.m_projectFiles = internalProjectFiles(ld);
+ ld.m_headerPaths = internalHeaderPaths(ld);
+ ld.m_definedMacros = internalDefinedMacros(ld);
+ ld.m_dirty = false;
}
-FilePaths CppModelManager::internalProjectFiles()
+FilePaths CppModelManagerPrivate::internalProjectFiles(SyncedProjectData &ld)
{
FilePaths files;
- for (const ProjectData &projectData : std::as_const(d->m_projectData)) {
+ for (const ProjectData &projectData : std::as_const(ld.m_projectData)) {
for (const ProjectPart::ConstPtr &part : projectData.projectInfo->projectParts()) {
for (const ProjectFile &file : part->files)
files += file.path;
@@ -1096,10 +1104,10 @@ FilePaths CppModelManager::internalProjectFiles()
return files;
}
-HeaderPaths CppModelManager::internalHeaderPaths()
+HeaderPaths CppModelManagerPrivate::internalHeaderPaths(SyncedProjectData &ld)
{
HeaderPaths headerPaths;
- for (const ProjectData &projectData: std::as_const(d->m_projectData)) {
+ for (const ProjectData &projectData : std::as_const(ld.m_projectData)) {
for (const ProjectPart::ConstPtr &part : projectData.projectInfo->projectParts()) {
for (const HeaderPath &path : part->headerPaths) {
HeaderPath hp(QDir::cleanPath(path.path), path.type);
@@ -1120,11 +1128,11 @@ static void addUnique(const Macros &newMacros, Macros &macros,
}
}
-Macros CppModelManager::internalDefinedMacros()
+Macros CppModelManagerPrivate::internalDefinedMacros(SyncedProjectData &ld)
{
Macros macros;
QSet<ProjectExplorer::Macro> alreadyIn;
- for (const ProjectData &projectData : std::as_const(d->m_projectData)) {
+ for (const ProjectData &projectData : std::as_const(ld.m_projectData)) {
for (const ProjectPart::ConstPtr &part : projectData.projectInfo->projectParts()) {
addUnique(part->toolChainMacros, macros, alreadyIn);
addUnique(part->projectMacros, macros, alreadyIn);
@@ -1351,15 +1359,19 @@ QFuture<void> CppModelManager::updateSourceFiles(const QSet<FilePath> &sourceFil
ProjectInfoList CppModelManager::projectInfos()
{
- QReadLocker locker(&d->m_projectLock);
- return Utils::transform<QList<ProjectInfo::ConstPtr>>(d->m_projectData,
- [](const ProjectData &d) { return d.projectInfo; });
+ return Utils::transform<QList<ProjectInfo::ConstPtr>>(d->m_lockedProjectData.readLocked()
+ ->m_projectData,
+ [](const ProjectData &d) {
+ return d.projectInfo;
+ });
}
ProjectInfo::ConstPtr CppModelManager::projectInfo(Project *project)
{
- QReadLocker locker(&d->m_projectLock);
- return d->m_projectData.value(project).projectInfo;
+ return d->m_lockedProjectData.get<ProjectInfo::ConstPtr>(
+ [project](const CppModelManagerPrivate::SyncedProjectData &ld) {
+ return ld.m_projectData.value(project).projectInfo;
+ });
}
/// \brief Remove all files and their includes (recursively) of given ProjectInfo from the snapshot.
@@ -1460,18 +1472,17 @@ private:
const QSet<FilePath> m_newSourceFiles;
};
-/// Make sure that m_projectLock is locked for writing when calling this.
-void CppModelManager::recalculateProjectPartMappings()
+void CppModelManagerPrivate::recalculateProjectPartMappings(SyncedProjectData &ld)
{
- d->m_projectPartIdToProjectProjectPart.clear();
- d->m_fileToProjectParts.clear();
- for (const ProjectData &projectData : std::as_const(d->m_projectData)) {
+ ld.m_projectPartIdToProjectProjectPart.clear();
+ ld.m_fileToProjectParts.clear();
+ for (const ProjectData &projectData : std::as_const(ld.m_projectData)) {
for (const ProjectPart::ConstPtr &projectPart : projectData.projectInfo->projectParts()) {
- d->m_projectPartIdToProjectProjectPart[projectPart->id()] = projectPart;
+ ld.m_projectPartIdToProjectProjectPart[projectPart->id()] = projectPart;
for (const ProjectFile &cxxFile : projectPart->files) {
- d->m_fileToProjectParts[cxxFile.path].append(projectPart);
+ ld.m_fileToProjectParts[cxxFile.path].append(projectPart);
if (FilePath canonical = cxxFile.path.canonicalPath(); canonical != cxxFile.path)
- d->m_fileToProjectParts[canonical].append(projectPart);
+ ld.m_fileToProjectParts[canonical].append(projectPart);
}
}
}
@@ -1483,12 +1494,15 @@ void CppModelManagerPrivate::setupWatcher(const QFuture<void> &future, Project *
ProjectData *projectData, CppModelManager *q)
{
projectData->indexer = new QFutureWatcher<void>(q);
- const auto handleFinished = [this, project, watcher = projectData->indexer, q] {
- if (const auto it = m_projectData.find(project);
- it != m_projectData.end() && it->indexer == watcher) {
- it->indexer = nullptr;
- it->fullyIndexed = !watcher->isCanceled();
- }
+ const auto handleFinished = [project, watcher = projectData->indexer, q] {
+ d->m_lockedProjectData.write([watcher, project](auto &ld) {
+ const auto it = ld.m_projectData.find(project);
+ if (it != ld.m_projectData.end() && it->indexer == watcher) {
+ it->indexer = nullptr;
+ it->fullyIndexed = !watcher->isCanceled();
+ }
+ });
+
watcher->disconnect(q);
watcher->deleteLater();
};
@@ -1542,17 +1556,21 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo::ConstPtr &ne
return {};
ProjectData *projectData = nullptr;
- { // Only hold the lock for a limited scope, so the dumping afterwards does not deadlock.
- QWriteLocker projectLocker(&d->m_projectLock);
+ d->m_lockedProjectData.write([&newProjectInfo,
+ project,
+ &filesToReindex,
+ &removedProjectParts,
+ &filesRemoved,
+ &projectData](auto &ld) {
const QSet<FilePath> newSourceFiles = newProjectInfo->sourceFiles();
// Check if we can avoid a full reindexing
- const auto it = d->m_projectData.find(project);
- if (it != d->m_projectData.end() && it->projectInfo && it->fullyIndexed) {
+ const auto it = ld.m_projectData.find(project);
+ if (it != ld.m_projectData.end() && it->projectInfo && it->fullyIndexed) {
ProjectInfoComparer comparer(*it->projectInfo, *newProjectInfo);
if (comparer.configurationOrFilesChanged()) {
- d->m_dirty = true;
+ ld.m_dirty = true;
// If the project configuration changed, do a full reindexing
if (comparer.configurationChanged()) {
@@ -1587,22 +1605,22 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo::ConstPtr &ne
// A new project was opened/created, do a full indexing
} else {
- d->m_dirty = true;
+ ld.m_dirty = true;
filesToReindex.unite(newSourceFiles);
}
// Update Project/ProjectInfo and File/ProjectPart table
- if (it != d->m_projectData.end()) {
+ if (it != ld.m_projectData.end()) {
if (it->indexer)
it->indexer->cancel();
it->projectInfo = newProjectInfo;
it->fullyIndexed = false;
}
- projectData = it == d->m_projectData.end()
- ? &(d->m_projectData[project] = ProjectData{newProjectInfo, nullptr, false})
- : &(*it);
- recalculateProjectPartMappings();
- } // Locker scope
+ projectData = it == ld.m_projectData.end() ? &(
+ ld.m_projectData[project] = ProjectData{newProjectInfo, nullptr, false})
+ : &(*it);
+ CppModelManagerPrivate::recalculateProjectPartMappings(ld);
+ });
// If requested, dump everything we got
if (DumpProjectInfo)
@@ -1639,25 +1657,38 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo::ConstPtr &ne
ProjectPart::ConstPtr CppModelManager::projectPartForId(const QString &projectPartId)
{
- QReadLocker locker(&d->m_projectLock);
- return d->m_projectPartIdToProjectProjectPart.value(projectPartId);
+ return d->m_lockedProjectData.get<ProjectPart::ConstPtr>(
+ [projectPartId](const CppModelManagerPrivate::SyncedProjectData &ld) {
+ return ld.m_projectPartIdToProjectProjectPart.value(projectPartId);
+ });
}
QList<ProjectPart::ConstPtr> CppModelManager::projectPart(const FilePath &fileName)
{
- {
- QReadLocker locker(&d->m_projectLock);
- auto it = d->m_fileToProjectParts.constFind(fileName);
- if (it != d->m_fileToProjectParts.constEnd())
- return it.value();
- }
+ std::optional<QList<ProjectPart::ConstPtr>> result;
+
+ d->m_lockedProjectData.read(
+ [&fileName, &result](const CppModelManagerPrivate::SyncedProjectData &sd) {
+ const auto it = sd.m_fileToProjectParts.constFind(fileName);
+ if (it != sd.m_fileToProjectParts.constEnd())
+ result = *it;
+ });
+
+ if (result)
+ return *result;
+
const FilePath canonicalPath = fileName.canonicalPath();
- QWriteLocker locker(&d->m_projectLock);
- const auto it = d->m_fileToProjectParts.constFind(canonicalPath);
- if (it == d->m_fileToProjectParts.constEnd())
- return {};
- d->m_fileToProjectParts.insert(fileName, it.value());
- return it.value();
+
+ d->m_lockedProjectData.write(
+ [&fileName, &canonicalPath, &result](CppModelManagerPrivate::SyncedProjectData &sd) {
+ const auto it = sd.m_fileToProjectParts.constFind(canonicalPath);
+ if (it == sd.m_fileToProjectParts.constEnd())
+ return;
+ sd.m_fileToProjectParts.insert(fileName, it.value());
+ result = it.value();
+ });
+
+ return result.value_or(QList<ProjectPart::ConstPtr>{});
}
QList<ProjectPart::ConstPtr> CppModelManager::projectPartFromDependencies(
@@ -1713,8 +1744,7 @@ void CppModelManager::emitAbstractEditorSupportRemoved(const QString &filePath)
void CppModelManager::onProjectAdded(Project *)
{
- QWriteLocker locker(&d->m_projectLock);
- d->m_dirty = true;
+ d->m_lockedProjectData.writeLocked()->m_dirty = true;
}
void CppModelManager::delayedGC()
@@ -1735,17 +1765,17 @@ void CppModelManager::onAboutToRemoveProject(Project *project)
{
QStringList idsOfRemovedProjectParts;
- {
- QWriteLocker locker(&d->m_projectLock);
- d->m_dirty = true;
- const QStringList projectPartsIdsBefore = d->m_projectPartIdToProjectProjectPart.keys();
+ d->m_lockedProjectData.write([project, &idsOfRemovedProjectParts](
+ CppModelManagerPrivate::SyncedProjectData &sd) {
+ sd.m_dirty = true;
+ const QStringList projectPartsIdsBefore = sd.m_projectPartIdToProjectProjectPart.keys();
- d->m_projectData.remove(project);
- recalculateProjectPartMappings();
+ sd.m_projectData.remove(project);
+ CppModelManagerPrivate::recalculateProjectPartMappings(sd);
- const QStringList projectPartsIdsAfter = d->m_projectPartIdToProjectProjectPart.keys();
+ const QStringList projectPartsIdsAfter = sd.m_projectPartIdToProjectProjectPart.keys();
idsOfRemovedProjectParts = removedProjectParts(projectPartsIdsBefore, projectPartsIdsAfter);
- }
+ });
if (!idsOfRemovedProjectParts.isEmpty())
emit m_instance->projectPartsRemoved(idsOfRemovedProjectParts);
@@ -1758,11 +1788,8 @@ void CppModelManager::onActiveProjectChanged(Project *project)
if (!project)
return; // Last project closed.
- {
- QReadLocker locker(&d->m_projectLock);
- if (!d->m_projectData.contains(project))
- return; // Not yet known to us.
- }
+ if (!d->m_lockedProjectData.readLocked()->m_projectData.contains(project))
+ return; // Not yet known to us.
updateCppEditorDocuments();
}
@@ -2103,32 +2130,33 @@ CppIndexingSupport *CppModelManager::indexingSupport()
FilePaths CppModelManager::projectFiles()
{
- QWriteLocker locker(&d->m_projectLock);
- ensureUpdated();
-
- return d->m_projectFiles;
+ return d->m_lockedProjectData.update<FilePaths>(
+ [](CppModelManagerPrivate::SyncedProjectData &sd) {
+ CppModelManagerPrivate::ensureUpdated(sd);
+ return sd.m_projectFiles;
+ });
}
HeaderPaths CppModelManager::headerPaths()
{
- QWriteLocker locker(&d->m_projectLock);
- ensureUpdated();
-
- return d->m_headerPaths;
+ return d->m_lockedProjectData.update<HeaderPaths>(
+ [](CppModelManagerPrivate::SyncedProjectData &sd) {
+ CppModelManagerPrivate::ensureUpdated(sd);
+ return sd.m_headerPaths;
+ });
}
void CppModelManager::setHeaderPaths(const HeaderPaths &headerPaths)
{
- QWriteLocker locker(&d->m_projectLock);
- d->m_headerPaths = headerPaths;
+ d->m_lockedProjectData.writeLocked()->m_headerPaths = headerPaths;
}
Macros CppModelManager::definedMacros()
{
- QWriteLocker locker(&d->m_projectLock);
- ensureUpdated();
-
- return d->m_definedMacros;
+ return d->m_lockedProjectData.update<Macros>([](CppModelManagerPrivate::SyncedProjectData &sd) {
+ CppModelManagerPrivate::ensureUpdated(sd);
+ return sd.m_definedMacros;
+ });
}
void CppModelManager::enableGarbageCollector(bool enable)
diff --git a/src/plugins/cppeditor/cppmodelmanager.h b/src/plugins/cppeditor/cppmodelmanager.h
index 8867d5cd0f..a229d98957 100644
--- a/src/plugins/cppeditor/cppmodelmanager.h
+++ b/src/plugins/cppeditor/cppmodelmanager.h
@@ -290,7 +290,6 @@ private:
static void setupFallbackProjectPart();
static void delayedGC();
- static void recalculateProjectPartMappings();
static void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot);
static void removeFilesFromSnapshot(const QSet<Utils::FilePath> &removedFiles);
@@ -298,11 +297,6 @@ private:
static WorkingCopy buildWorkingCopyList();
- static void ensureUpdated();
- static Utils::FilePaths internalProjectFiles();
- static ProjectExplorer::HeaderPaths internalHeaderPaths();
- static ProjectExplorer::Macros internalDefinedMacros();
-
static void dumpModelManagerConfiguration(const QString &logFileId);
static void initCppTools();
};