CppProjectUpdater: Wait for all tasks to be finished in d'tor

It may happen that the old task was canceled and still running
while the new task was started. Later, when the d'tor is called
both old and new tasks may still be running. Before we waited only
for the new task to be finished in d'tor. Now we are waiting
for all tasks to be finished.

Amends: 7fb592fe0c

Task-number: QTCREATORBUG-25709
Change-Id: Id4b44cd36ee03aa45472b15d8fbb25a2cab77e92
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Jarek Kobus
2021-05-26 09:06:06 +02:00
parent ff0ff1a3b5
commit 03b7324325
2 changed files with 10 additions and 24 deletions

View File

@@ -43,11 +43,7 @@ CppProjectUpdater::CppProjectUpdater()
&QFutureWatcher<ProjectInfo>::finished, &QFutureWatcher<ProjectInfo>::finished,
this, this,
&CppProjectUpdater::onProjectInfoGenerated); &CppProjectUpdater::onProjectInfoGenerated);
} m_futureSynchronizer.setCancelOnWait(true);
CppProjectUpdater::~CppProjectUpdater()
{
cancelAndWaitForFinished();
} }
void CppProjectUpdater::update(const ProjectExplorer::ProjectUpdateInfo &projectUpdateInfo) void CppProjectUpdater::update(const ProjectExplorer::ProjectUpdateInfo &projectUpdateInfo)
@@ -63,30 +59,21 @@ void CppProjectUpdater::update(const ProjectExplorer::ProjectUpdateInfo &project
this, &CppProjectUpdater::onToolChainRemoved); this, &CppProjectUpdater::onToolChainRemoved);
// Run the project info generator in a worker thread and continue if that one is finished. // Run the project info generator in a worker thread and continue if that one is finished.
m_generateFuture = Utils::runAsync([=](QFutureInterface<ProjectInfo> &futureInterface) { auto generateFuture = Utils::runAsync([=](QFutureInterface<ProjectInfo> &futureInterface) {
ProjectUpdateInfo fullProjectUpdateInfo = projectUpdateInfo; ProjectUpdateInfo fullProjectUpdateInfo = projectUpdateInfo;
if (fullProjectUpdateInfo.rppGenerator) if (fullProjectUpdateInfo.rppGenerator)
fullProjectUpdateInfo.rawProjectParts = fullProjectUpdateInfo.rppGenerator(); fullProjectUpdateInfo.rawProjectParts = fullProjectUpdateInfo.rppGenerator();
Internal::ProjectInfoGenerator generator(futureInterface, fullProjectUpdateInfo); Internal::ProjectInfoGenerator generator(futureInterface, fullProjectUpdateInfo);
futureInterface.reportResult(generator.generate()); futureInterface.reportResult(generator.generate());
}); });
m_generateFutureWatcher.setFuture(m_generateFuture); m_generateFutureWatcher.setFuture(generateFuture);
m_futureSynchronizer.addFuture(generateFuture);
} }
void CppProjectUpdater::cancel() void CppProjectUpdater::cancel()
{ {
m_generateFutureWatcher.setFuture({}); m_generateFutureWatcher.setFuture({});
m_generateFuture.cancel(); m_futureSynchronizer.cancelAllFutures();
m_updateFuture.cancel();
}
void CppProjectUpdater::cancelAndWaitForFinished()
{
cancel();
if (m_generateFuture.isRunning())
m_generateFuture.waitForFinished();
if (m_updateFuture.isRunning())
m_updateFuture.waitForFinished();
} }
void CppProjectUpdater::onToolChainRemoved(ProjectExplorer::ToolChain *t) void CppProjectUpdater::onToolChainRemoved(ProjectExplorer::ToolChain *t)
@@ -106,8 +93,9 @@ void CppProjectUpdater::onProjectInfoGenerated()
if (m_generateFutureWatcher.isCanceled() || m_generateFutureWatcher.future().resultCount() < 1) if (m_generateFutureWatcher.isCanceled() || m_generateFutureWatcher.future().resultCount() < 1)
return; return;
m_updateFuture = CppModelManager::instance()->updateProjectInfo( auto updateFuture = CppModelManager::instance()->updateProjectInfo(
m_generateFutureWatcher.result()); m_generateFutureWatcher.result());
m_futureSynchronizer.addFuture(updateFuture);
} }
CppProjectUpdaterFactory::CppProjectUpdaterFactory() CppProjectUpdaterFactory::CppProjectUpdaterFactory()

View File

@@ -29,6 +29,8 @@
#include "cpptools_global.h" #include "cpptools_global.h"
#include "projectinfo.h" #include "projectinfo.h"
#include <utils/futuresynchronizer.h>
#include <QFutureWatcher> #include <QFutureWatcher>
namespace CppTools { namespace CppTools {
@@ -52,23 +54,19 @@ class CPPTOOLS_EXPORT CppProjectUpdater final : public QObject, public CppProjec
public: public:
CppProjectUpdater(); CppProjectUpdater();
~CppProjectUpdater() override;
void update(const ProjectExplorer::ProjectUpdateInfo &projectUpdateInfo) override; void update(const ProjectExplorer::ProjectUpdateInfo &projectUpdateInfo) override;
void cancel() override; void cancel() override;
private: private:
void cancelAndWaitForFinished();
void onToolChainRemoved(ProjectExplorer::ToolChain *); void onToolChainRemoved(ProjectExplorer::ToolChain *);
void onProjectInfoGenerated(); void onProjectInfoGenerated();
private: private:
ProjectExplorer::ProjectUpdateInfo m_projectUpdateInfo; ProjectExplorer::ProjectUpdateInfo m_projectUpdateInfo;
QFuture<ProjectInfo> m_generateFuture;
QFuture<void> m_updateFuture;
QFutureWatcher<ProjectInfo> m_generateFutureWatcher; QFutureWatcher<ProjectInfo> m_generateFutureWatcher;
Utils::FutureSynchronizer m_futureSynchronizer;
}; };
} // namespace CppTools } // namespace CppTools