AsyncTask: Centralize setting global future synchronizer

Move the global FutureSynchronizer to Utils and use it
by default for AsyncTask (if that is in the main thread).
This way setting a synchronizer is less prone to be forgotten.
Individual uses can still override this.

Change-Id: I1a12bf4d7f4cb5be99668bf0a4797108c2fe6448
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
Eike Ziller
2024-05-16 09:29:51 +02:00
parent 3cd72806f8
commit c676ec825f
28 changed files with 31 additions and 78 deletions

View File

@@ -17,8 +17,8 @@
#include <utils/futuresynchronizer.h>
#include <utils/hostosinfo.h>
#include <utils/mimeutils.h>
#include <utils/qtcprocess.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/qtcsettings.h>
#include <utils/threadutils.h>
@@ -436,7 +436,7 @@ QString PluginManager::systemInformation()
FutureSynchronizer *PluginManager::futureSynchronizer()
{
return d->m_futureSynchronizer.get();
return Utils::futureSynchronizer();
}
/*!
@@ -981,10 +981,7 @@ void PluginManagerPrivate::startDelayedInitialize()
*/
PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) :
q(pluginManager)
{
m_futureSynchronizer.reset(new FutureSynchronizer);
}
{}
/*!
\internal
@@ -1047,7 +1044,11 @@ void PluginManagerPrivate::stopAll()
*/
void PluginManagerPrivate::deleteAll()
{
m_futureSynchronizer.reset(); // Synchronize all futures from all plugins
// Guard against someone playing with the setting
QTC_ASSERT(
Utils::futureSynchronizer()->isCancelOnWait(),
Utils::futureSynchronizer()->cancelAllFutures());
Utils::futureSynchronizer()->waitForFinished(); // Synchronize all futures from all plugins
Utils::reverseForeach(loadQueue(), [this](PluginSpec *spec) {
loadPlugin(spec, PluginSpec::Deleted);
});

View File

@@ -136,7 +136,6 @@ public:
QWaitCondition m_scenarioWaitCondition;
PluginManager::ProcessData m_creatorProcessData;
std::unique_ptr<Utils::FutureSynchronizer> m_futureSynchronizer;
private:
PluginManager *q;

View File

@@ -7,6 +7,7 @@
#include "futuresynchronizer.h"
#include "qtcassert.h"
#include "threadutils.h"
#include <solutions/tasking/tasktree.h>
@@ -130,7 +131,9 @@ template <typename ResultType>
class Async : public AsyncBase
{
public:
Async() {
Async()
: m_synchronizer(isMainThread() ? futureSynchronizer() : nullptr)
{
connect(&m_watcher, &QFutureWatcherBase::finished, this, &AsyncBase::done);
connect(&m_watcher, &QFutureWatcherBase::resultReadyAt, this, &AsyncBase::resultReadyAt);
}

View File

@@ -3,6 +3,9 @@
#include "futuresynchronizer.h"
#include "qtcassert.h"
#include "threadutils.h"
/*!
\class Utils::FutureSynchronizer
\inmodule QtCreator
@@ -62,4 +65,18 @@ void FutureSynchronizer::flushFinishedFutures()
m_futures = newFutures;
}
Q_GLOBAL_STATIC(FutureSynchronizer, s_futureSynchronizer);
/*!
Returns a global FutureSynchronizer.
The application should cancel and wait for the tasks in this synchronizer before actually
unloading any libraries. This is for example done by the plugin manager in Qt Creator.
May only be accessed by the main thread.
*/
FutureSynchronizer *futureSynchronizer()
{
QTC_ASSERT(isMainThread(), return nullptr);
return s_futureSynchronizer;
}
} // namespace Utils

View File

@@ -42,4 +42,6 @@ private:
bool m_cancelOnWait = true;
};
QTCREATOR_UTILS_EXPORT FutureSynchronizer *futureSynchronizer();
} // namespace Utils

View File

@@ -8,14 +8,11 @@
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <solutions/tasking/barrier.h>
#include <solutions/tasking/networkquery.h>
#include <utils/async.h>
#include <utils/filepath.h>
#include <utils/futuresynchronizer.h>
#include <utils/networkaccessmanager.h>
#include <utils/unarchiver.h>
@@ -170,7 +167,6 @@ GroupItem downloadSdkRecipe()
return SetupResult::StopWithError;
async.setConcurrentCallData(validateFileIntegrity, *storage->sdkFileName,
androidConfig().getSdkToolsSha256());
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
storage->progressDialog->setRange(0, 0);
storage->progressDialog->setLabelText(Tr::tr("Verifying package integrity..."));
return SetupResult::Continue;

View File

@@ -19,7 +19,6 @@
#include <coreplugin/navigationwidget.h>
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/project.h>
@@ -496,7 +495,6 @@ static Group dtoRecipe(const Storage<DtoStorageType<DtoType>> &dtoStorage)
const auto deserialize = [](QPromise<expected_str<DtoType>> &promise, const QByteArray &input) {
promise.addResult(DtoType::deserializeExpected(input));
};
task.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
task.setConcurrentCallData(deserialize, **storage);
return SetupResult::Continue;
};

View File

@@ -10,8 +10,6 @@
#include <cppeditor/cppeditortr.h>
#include <cppeditor/cpplocatorfilter.h>
#include <extensionsystem/pluginmanager.h>
#include <languageclient/currentdocumentsymbolsrequest.h>
#include <languageclient/locatorfilter.h>
@@ -186,7 +184,6 @@ static LocatorMatcherTask currentDocumentMatcher()
};
const auto onFilterSetup = [=](Async<void> &async) {
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(filterCurrentResults, *storage, *resultStorage,
TextDocument::currentTextDocument()->plainText());
};

View File

@@ -14,8 +14,6 @@
#include <cppeditor/cppprojectfile.h>
#include <cppeditor/cpptoolsreuse.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/async.h>
#include <utils/qtcprocess.h>
#include <utils/qtcassert.h>
@@ -208,7 +206,6 @@ GroupItem clangToolTask(const AnalyzeUnits &units,
data.setConcurrentCallData(&parseDiagnostics,
storage->outputFilePath,
input.diagnosticsFilter);
data.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
};
const auto onReadDone = [storage, input, outputHandler, iterator](
const Async<expected_str<Diagnostics>> &data, DoneWith result) {

View File

@@ -10,8 +10,6 @@
#include "icore.h"
#include "locator/locatormanager.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/async.h>
#include <utils/fuzzymatcher.h>
@@ -192,7 +190,6 @@ LocatorMatcherTasks ActionsFilter::matchers()
storage->reportOutput(m_entries);
return SetupResult::StopWithSuccess;
}
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(matches, *storage, m_entries);
return SetupResult::Continue;
};

View File

@@ -6,8 +6,6 @@
#include "locator.h"
#include "../coreplugintr.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/async.h>
#include <utils/fileutils.h>
@@ -89,7 +87,6 @@ DirectoryFilter::DirectoryFilter(Id id)
return SetupResult::StopWithSuccess; // Group stops, skips async task
};
const auto onSetup = [this](Async<FilePaths> &async) {
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(&refresh, m_directories, m_filters, m_exclusionFilters,
displayName());
};

View File

@@ -10,8 +10,6 @@
#include "../vcsmanager.h"
#include "locatormanager.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/async.h>
#include <utils/checkablemessagebox.h>
@@ -312,7 +310,6 @@ LocatorMatcherTasks FileSystemFilter::matchers()
const auto onSetup = [storage, includeHidden = m_includeHidden, shortcut = shortcutString()]
(Async<void> &async) {
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(matches, *storage, shortcut,
DocumentManager::fileDialogInitialDirectory(), includeHidden);
};

View File

@@ -1464,7 +1464,6 @@ LocatorMatcherTask LocatorFileCache::matcher() const
// no provider is set or it returned empty generator
that->bumpExecutionId();
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(&filter, *storage, *that);
return SetupResult::Continue;
};

View File

@@ -6,8 +6,6 @@
#include "../coreplugintr.h"
#include "../editormanager/documentmodel.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/async.h>
#include <utils/link.h>
@@ -77,7 +75,6 @@ LocatorMatcherTasks OpenDocumentsFilter::matchers()
const auto onSetup = [storage](Async<void> &async) {
const QList<Entry> editorsData = Utils::transform(DocumentModel::entries(),
[](const DocumentModel::Entry *e) { return Entry{e->filePath(), e->displayName()}; });
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(matchEditors, *storage, editorsData);
};

View File

@@ -6,8 +6,6 @@
#include "../coreplugintr.h"
#include "../messagemanager.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/async.h>
#include <utils/commandline.h>
@@ -198,7 +196,6 @@ LocatorMatcherTasks SpotlightLocatorFilter::matchers()
? insensArgs : sensArgs;
const CommandLine cmd(FilePath::fromString(command), expander->expand(args),
CommandLine::Raw);
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(matches, *storage, cmd, sortResults);
return SetupResult::Continue;
};

View File

@@ -242,7 +242,6 @@ public:
return SetupResult::StopWithError;
async.setConcurrentCallData(checkContents, m_tempDir->path());
async.setFutureSynchronizer(PluginManager::futureSynchronizer());
return SetupResult::Continue;
};
const auto onCheckerDone = [this](const Async<ArchiveIssue> &async) {

View File

@@ -11,8 +11,6 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/async.h>
#include <utils/fuzzymatcher.h>
@@ -108,7 +106,6 @@ LocatorMatcherTask locatorMatcher(IndexItem::ItemType type, const EntryFromIndex
Storage<LocatorStorage> storage;
const auto onSetup = [=](Async<void> &async) {
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(matchesFor, *storage, type, converter);
};
return {AsyncTask<void>(onSetup), storage};
@@ -306,7 +303,6 @@ LocatorMatcherTask currentDocumentMatcher()
Storage<LocatorStorage> storage;
const auto onSetup = [=](Async<void> &async) {
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(matchesForCurrentDocument, *storage, currentFileName());
};
return {AsyncTask<void>(onSetup), storage};

View File

@@ -13,8 +13,6 @@
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/textdocument.h>
#include <utils/async.h>
@@ -121,7 +119,6 @@ DiffFilesController::DiffFilesController(IDocument *document)
const auto onDiffSetup = [this, reloadInput = inputList.at(i)](Async<FileData> &async) {
async.setConcurrentCallData(
DiffFile(ignoreWhitespace(), contextLineCount()), reloadInput);
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
};
const auto onDiffDone = [outputList, i](const Async<FileData> &async) {

View File

@@ -12,8 +12,6 @@
#include <coreplugin/minisplitter.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/displaysettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/textdocument.h>
@@ -868,7 +866,6 @@ void SideBySideDiffEditorWidget::restoreState()
void SideBySideDiffEditorWidget::showDiff()
{
m_asyncTask.reset(new Async<SideBySideShowResults>());
m_asyncTask->setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
m_controller.setBusyShowing(true);
connect(m_asyncTask.get(), &AsyncBase::done, this, [this] {

View File

@@ -10,8 +10,6 @@
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/fontsettings.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditorsettings.h>
@@ -451,7 +449,6 @@ void UnifiedDiffEditorWidget::showDiff()
}
m_asyncTask.reset(new Async<UnifiedShowResult>());
m_asyncTask->setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
m_controller.setBusyShowing(true);
connect(m_asyncTask.get(), &AsyncBase::done, this, [this] {
if (m_asyncTask->isCanceled() || !m_asyncTask->isResultAvailable()) {

View File

@@ -10,7 +10,6 @@
#include <coreplugin/helpmanager.h>
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/async.h>
#include <utils/utilsicons.h>
@@ -95,7 +94,6 @@ LocatorMatcherTasks HelpIndexFilter::matchers()
}
const QStringList cache = m_lastEntry.isEmpty() || !storage->input().contains(m_lastEntry)
? m_allIndicesCache : m_lastIndicesCache;
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(matches, *storage, cache, m_icon);
};
const auto onDone = [this, storage](const Async<QStringList> &async) {

View File

@@ -8,8 +8,6 @@
#include "languageclientmanager.h"
#include "languageclienttr.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/async.h>
#include <utils/fuzzymatcher.h>
@@ -70,7 +68,6 @@ LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount,
const QList<SymbolInformation> results = *resultStorage;
if (results.isEmpty())
return SetupResult::StopWithSuccess;
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(filterResults, *storage, client, results, filter);
return SetupResult::Continue;
};
@@ -130,7 +127,6 @@ LocatorMatcherTask currentDocumentMatcher()
};
const auto onFilterSetup = [storage, resultStorage](Async<void> &async) {
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(filterCurrentResults, *storage, *resultStorage);
};

View File

@@ -11,8 +11,6 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/idocument.h>
#include <extensionsystem/pluginmanager.h>
#include <solutions/tasking/tasktreerunner.h>
#include <utils/async.h>
@@ -326,7 +324,6 @@ GroupItem ProcessExtraCompiler::taskItemImpl(const ContentProvider &provider)
const auto onSetup = [this, provider](Async<FileNameToContentsHash> &async) {
async.setThreadPool(extraCompilerThreadPool());
// The passed synchronizer has cancelOnWait set to true by default.
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(&ProcessExtraCompiler::runInThread, this, command(),
workingDirectory(), arguments(), provider, buildEnvironment());
};

View File

@@ -751,11 +751,9 @@ PythonSettings::PythonSettings()
initFromSettings(Core::ICore::settings());
const auto onRegistrySetup = [](Async<QList<Interpreter>> &task) {
task.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
task.setConcurrentCallData(pythonsFromRegistry);
};
const auto onPathSetup = [](Async<QList<Interpreter>> &task) {
task.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
task.setConcurrentCallData(pythonsFromPath);
};
const auto onTaskDone = [](const Async<QList<Interpreter>> &task) {

View File

@@ -5,8 +5,6 @@
#include "qmljslocatordata.h"
#include "qmljstoolstr.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/async.h>
@@ -81,7 +79,6 @@ LocatorMatcherTasks QmlJSFunctionsFilter::matchers()
Storage<LocatorStorage> storage;
const auto onSetup = [storage, entries = m_data->entries()](Async<void> &async) {
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(matches, *storage, entries);
};

View File

@@ -15,8 +15,6 @@
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/devicesupport/filetransfer.h>
#include <projectexplorer/devicesupport/filetransferinterface.h>
@@ -1622,8 +1620,6 @@ private:
const auto onCreateDirSetup = [iteratorParentDirs](Async<expected_str<void>> &async) {
async.setConcurrentCallData(createDir, *iteratorParentDirs);
if (Utils::isMainThread())
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
};
const auto onCreateDirDone = [this,
@@ -1641,8 +1637,6 @@ private:
const auto onCopySetup = [iterator](Async<expected_str<void>> &async) {
async.setConcurrentCallData(copyFile, *iterator);
if (Utils::isMainThread())
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
};
const auto onCopyDone = [this, iterator, counterStorage](

View File

@@ -7,8 +7,6 @@
#include "remotelinuxtr.h"
#include "utils/async.h"
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/devicesupport/filetransfer.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -102,7 +100,6 @@ GroupItem GenericLinuxDeviceTesterPrivate::connectionTask() const
const auto onSetup = [this](Async<bool> &task) {
emit q->progressMessage(Tr::tr("Connecting to device..."));
task.setConcurrentCallData([device = m_device] { return device->tryToConnect(); });
task.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
};
const auto onDone = [this](const Async<bool> &task) {
const bool success = task.isResultAvailable() && task.result();

View File

@@ -3,11 +3,8 @@
#include "vcsbasediffeditorcontroller.h"
#include <extensionsystem/pluginmanager.h>
#include <utils/async.h>
#include <utils/environment.h>
#include <utils/futuresynchronizer.h>
#include <utils/qtcprocess.h>
using namespace DiffEditor;
@@ -41,7 +38,6 @@ VcsBaseDiffEditorController::~VcsBaseDiffEditorController()
GroupItem VcsBaseDiffEditorController::postProcessTask(const Storage<QString> &inputStorage)
{
const auto onSetup = [inputStorage](Async<QList<FileData>> &async) {
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
async.setConcurrentCallData(&DiffUtils::readPatchWithPromise, *inputStorage);
};
const auto onDone = [this](const Async<QList<FileData>> &async, DoneWith result) {