CppProjectUpdater: Reuse TaskTree

Change-Id: I7474e5a31d169bf435d94536cffd77d218320977
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Jarek Kobus
2023-01-04 13:05:36 +01:00
parent 76260f8038
commit 1e10161bf2
5 changed files with 64 additions and 109 deletions

View File

@@ -27,6 +27,7 @@
#include <cppeditor/generatedcodemodelsupport.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/extracompiler.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>

View File

@@ -68,6 +68,7 @@
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectpanelfactory.h>
#include <projectexplorer/projecttree.h>

View File

@@ -7,15 +7,13 @@
#include "cppprojectinfogenerator.h"
#include "generatedcodemodelsupport.h"
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/taskprogress.h>
#include <projectexplorer/toolchainmanager.h>
#include <projectexplorer/extracompiler.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/asynctask.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <utils/tasktree.h>
#include <QFutureInterface>
@@ -26,17 +24,10 @@ namespace CppEditor {
CppProjectUpdater::CppProjectUpdater()
{
connect(&m_generateFutureWatcher,
&QFutureWatcher<ProjectInfo>::finished,
this,
&CppProjectUpdater::onProjectInfoGenerated);
m_futureSynchronizer.setCancelOnWait(true);
}
CppProjectUpdater::~CppProjectUpdater()
{
cancel();
}
CppProjectUpdater::~CppProjectUpdater() = default;
void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo)
{
@@ -49,102 +40,76 @@ void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo,
// Stop previous update.
cancel();
m_extraCompilers = Utils::transform(extraCompilers, [](ExtraCompiler *compiler) {
const QList<QPointer<ProjectExplorer::ExtraCompiler>> compilers =
Utils::transform(extraCompilers, [](ExtraCompiler *compiler) {
return QPointer<ExtraCompiler>(compiler);
});
m_projectUpdateInfo = projectUpdateInfo;
using namespace ProjectExplorer;
// Run the project info generator in a worker thread and continue if that one is finished.
auto generateFuture = Utils::runAsync([=](QFutureInterface<ProjectInfo::ConstPtr> &futureInterface) {
const auto infoGenerator = [=](QFutureInterface<ProjectInfo::ConstPtr> &futureInterface) {
ProjectUpdateInfo fullProjectUpdateInfo = projectUpdateInfo;
if (fullProjectUpdateInfo.rppGenerator)
fullProjectUpdateInfo.rawProjectParts = fullProjectUpdateInfo.rppGenerator();
Internal::ProjectInfoGenerator generator(futureInterface, fullProjectUpdateInfo);
futureInterface.reportResult(generator.generate());
});
m_generateFutureWatcher.setFuture(generateFuture);
m_futureSynchronizer.addFuture(generateFuture);
// extra compilers
for (QPointer<ExtraCompiler> compiler : std::as_const(m_extraCompilers)) {
if (!compiler->isDirty())
continue;
const auto destroyTaskTree = [this](TaskTree *taskTree) {
m_extraCompilerTasks.remove(taskTree);
taskTree->deleteLater();
};
TaskTree *taskTree = new TaskTree({compiler->compileFileItem()});
connect(taskTree, &TaskTree::done, this, [this, taskTree, destroyTaskTree] {
destroyTaskTree(taskTree);
m_projectUpdateFutureInterface->setProgressValue(
m_projectUpdateFutureInterface->progressValue() + 1);
checkForExtraCompilersFinished();
});
connect(taskTree, &TaskTree::errorOccurred, this, [taskTree, destroyTaskTree] {
destroyTaskTree(taskTree);
});
m_extraCompilerTasks.insert(taskTree);
taskTree->start();
using namespace Tasking;
struct UpdateStorage {
ProjectInfo::ConstPtr projectInfo = nullptr;
};
const TreeStorage<UpdateStorage> storage;
const auto setupInfoGenerator = [=](AsyncTask<ProjectInfo::ConstPtr> &async) {
async.setAsyncCallData(infoGenerator);
async.setFutureSynchronizer(&m_futureSynchronizer);
};
const auto onInfoGeneratorDone = [=](const AsyncTask<ProjectInfo::ConstPtr> &async) {
storage->projectInfo = async.result();
};
QList<TaskItem> tasks{parallel};
tasks.append(Async<ProjectInfo::ConstPtr>(setupInfoGenerator, onInfoGeneratorDone));
for (QPointer<ExtraCompiler> compiler : compilers) {
if (compiler && compiler->isDirty())
tasks.append(compiler->compileFileItem());
}
m_projectUpdateFutureInterface.reset(new QFutureInterface<void>);
m_projectUpdateFutureInterface->setProgressRange(0, m_extraCompilerTasks.size()
+ 1 /*generateFuture*/);
m_projectUpdateFutureInterface->setProgressValue(0);
m_projectUpdateFutureInterface->reportStarted();
Core::ProgressManager::addTask(m_projectUpdateFutureInterface->future(),
tr("Preparing C++ Code Model"),
"CppProjectUpdater");
}
void CppProjectUpdater::cancel()
{
if (m_projectUpdateFutureInterface && m_projectUpdateFutureInterface->isRunning())
m_projectUpdateFutureInterface->reportFinished();
m_generateFutureWatcher.setFuture({});
m_isProjectInfoGenerated = false;
qDeleteAll(m_extraCompilerTasks);
m_extraCompilerTasks.clear();
m_extraCompilers.clear();
m_futureSynchronizer.cancelAllFutures();
}
void CppProjectUpdater::onProjectInfoGenerated()
{
if (m_generateFutureWatcher.isCanceled() || m_generateFutureWatcher.future().resultCount() < 1)
return;
m_projectUpdateFutureInterface->setProgressValue(m_projectUpdateFutureInterface->progressValue()
+ 1);
m_isProjectInfoGenerated = true;
checkForExtraCompilersFinished();
}
void CppProjectUpdater::checkForExtraCompilersFinished()
{
if (!m_extraCompilerTasks.isEmpty() || !m_isProjectInfoGenerated)
return; // still need to wait
m_projectUpdateFutureInterface->reportFinished();
m_projectUpdateFutureInterface.reset();
const auto onDone = [this, storage, compilers] {
QList<ExtraCompiler *> extraCompilers;
QSet<FilePath> compilerFiles;
for (const QPointer<ExtraCompiler> &compiler : std::as_const(m_extraCompilers)) {
for (const QPointer<ExtraCompiler> &compiler : compilers) {
if (compiler) {
extraCompilers += compiler.data();
compilerFiles += Utils::toSet(compiler->targets());
}
}
GeneratedCodeModelSupport::update(extraCompilers);
m_extraCompilers.clear();
auto updateFuture = CppModelManager::instance()
->updateProjectInfo(m_generateFutureWatcher.result(), compilerFiles);
auto updateFuture = CppModelManager::instance()->updateProjectInfo(storage->projectInfo,
compilerFiles);
m_futureSynchronizer.addFuture(updateFuture);
m_taskTree.release()->deleteLater();
};
const auto onError = [this] {
m_taskTree.release()->deleteLater();
};
const Group root {
Storage(storage),
Group(tasks),
OnGroupDone(onDone),
OnGroupError(onError)
};
m_taskTree.reset(new TaskTree(root));
auto progress = new Core::TaskProgress(m_taskTree.get());
progress->setDisplayName(tr("Preparing C++ Code Model"));
m_taskTree->start();
}
void CppProjectUpdater::cancel()
{
m_taskTree.reset();
m_futureSynchronizer.cancelAllFutures();
}
namespace Internal {

View File

@@ -4,18 +4,15 @@
#pragma once
#include "cppeditor_global.h"
#include "cppprojectupdaterinterface.h"
#include "projectinfo.h"
#include <projectexplorer/extracompiler.h>
#include "cppprojectupdaterinterface.h"
#include <utils/futuresynchronizer.h>
#include <QFutureWatcher>
namespace ProjectExplorer { class ExtraCompiler; }
namespace Utils { class TaskTree; }
namespace CppEditor {
class ProjectInfo;
namespace Internal {
@@ -46,18 +43,8 @@ public:
void cancel() override;
private:
void onProjectInfoGenerated();
void checkForExtraCompilersFinished();
private:
ProjectExplorer::ProjectUpdateInfo m_projectUpdateInfo;
QList<QPointer<ProjectExplorer::ExtraCompiler>> m_extraCompilers;
QFutureWatcher<ProjectInfo::ConstPtr> m_generateFutureWatcher;
bool m_isProjectInfoGenerated = false;
QSet<Utils::TaskTree *> m_extraCompilerTasks;
std::unique_ptr<QFutureInterface<void>> m_projectUpdateFutureInterface;
Utils::FutureSynchronizer m_futureSynchronizer;
std::unique_ptr<Utils::TaskTree> m_taskTree;
};
} // namespace CppEditor

View File

@@ -26,6 +26,7 @@
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/extracompiler.h>
#include <projectexplorer/headerpath.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>