diff options
Diffstat (limited to 'src')
48 files changed, 863 insertions, 1071 deletions
diff --git a/src/plugins/clangpchmanager/clangpchmanager-source.pri b/src/plugins/clangpchmanager/clangpchmanager-source.pri index 98010437c0..27e35dc740 100644 --- a/src/plugins/clangpchmanager/clangpchmanager-source.pri +++ b/src/plugins/clangpchmanager/clangpchmanager-source.pri @@ -12,10 +12,7 @@ HEADERS += \ $$PWD/pchmanagerconnectionclient.h \ $$PWD/clangpchmanager_global.h \ $$PWD/projectupdater.h \ - $$PWD/pchmanagerprojectupdater.h \ - $$PWD/precompiledheaderstorage.h \ - $$PWD/precompiledheaderstorageinterface.h - + $$PWD/pchmanagerprojectupdater.h SOURCES += \ $$PWD/pchmanagerclient.cpp \ @@ -23,4 +20,3 @@ SOURCES += \ $$PWD/pchmanagerconnectionclient.cpp \ $$PWD/projectupdater.cpp \ $$PWD/pchmanagerprojectupdater.cpp - diff --git a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp index 5817db9034..098faf50b3 100644 --- a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp +++ b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp @@ -27,7 +27,6 @@ #include "pchmanagerconnectionclient.h" #include "pchmanagerclient.h" -#include "precompiledheaderstorage.h" #include "qtcreatorprojectupdater.h" #include <filepathcaching.h> @@ -62,8 +61,7 @@ public: Sqlite::Database database{Utils::PathString{Core::ICore::userResourcePath() + "/symbol-experimental-v1.db"}, 1000ms}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; ClangBackEnd::FilePathCaching filePathCache{database}; - PrecompiledHeaderStorage<> preCompiledHeaderStorage{database}; - PchManagerClient pchManagerClient{preCompiledHeaderStorage}; + PchManagerClient pchManagerClient; PchManagerConnectionClient connectionClient{&pchManagerClient}; QtCreatorProjectUpdater<PchManagerProjectUpdater> projectUpdate{connectionClient.serverProxy(), pchManagerClient, diff --git a/src/plugins/clangpchmanager/pchmanagerclient.cpp b/src/plugins/clangpchmanager/pchmanagerclient.cpp index e5321865ce..81af53308e 100644 --- a/src/plugins/clangpchmanager/pchmanagerclient.cpp +++ b/src/plugins/clangpchmanager/pchmanagerclient.cpp @@ -34,11 +34,6 @@ namespace ClangPchManager { -PchManagerClient::PchManagerClient(PrecompiledHeaderStorageInterface &precompiledHeaderStorage) - : m_precompiledHeaderStorage(precompiledHeaderStorage) -{ -} - void PchManagerClient::alive() { if (m_connectionClient) @@ -50,7 +45,6 @@ void PchManagerClient::precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeader for (ClangBackEnd::ProjectPartPch &projectPartPch : message.takeProjectPartPchs()) { const QString projectPartId{projectPartPch.projectPartId}; const QString pchPath{projectPartPch.pchPath}; - addPchToDatabase(projectPartPch); addProjectPartPch(std::move(projectPartPch)); precompiledHeaderUpdated(projectPartId, pchPath, projectPartPch.lastModified); } @@ -60,7 +54,6 @@ void PchManagerClient::precompiledHeaderRemoved(const QString &projectPartId) { for (auto notifier : m_notifiers) { Utils::SmallString id(projectPartId); - removePchFromDatabase(id); removeProjectPartPch(id); notifier->precompiledHeaderRemoved(projectPartId); } @@ -117,18 +110,6 @@ void PchManagerClient::removeProjectPartPch(Utils::SmallStringView projectPartId } } -void PchManagerClient::addPchToDatabase(const ClangBackEnd::ProjectPartPch &projectPartPch) -{ - m_precompiledHeaderStorage.insertPrecompiledHeader(projectPartPch.projectPartId, - projectPartPch.pchPath, - projectPartPch.lastModified); -} - -void PchManagerClient::removePchFromDatabase(const Utils::SmallStringView &projectPartId) -{ - m_precompiledHeaderStorage.deletePrecompiledHeader(projectPartId); -} - void PchManagerClient::addProjectPartPch(ClangBackEnd::ProjectPartPch &&projectPartPch) { auto found = std::lower_bound(m_projectPartPchs.begin(), diff --git a/src/plugins/clangpchmanager/pchmanagerclient.h b/src/plugins/clangpchmanager/pchmanagerclient.h index e9b80ebe51..92c44465f2 100644 --- a/src/plugins/clangpchmanager/pchmanagerclient.h +++ b/src/plugins/clangpchmanager/pchmanagerclient.h @@ -26,7 +26,6 @@ #pragma once #include "clangpchmanager_global.h" -#include "precompiledheaderstorageinterface.h" #include <pchmanagerclientinterface.h> #include <projectpartpchproviderinterface.h> @@ -43,7 +42,7 @@ class CLANGPCHMANAGER_EXPORT PchManagerClient final : public ClangBackEnd::PchMa { friend class PchManagerNotifierInterface; public: - PchManagerClient(PrecompiledHeaderStorageInterface &precompiledHeaderStorage); + PchManagerClient() = default; void alive() override; void precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) override; @@ -71,14 +70,10 @@ unittest_public: void addProjectPartPch(ClangBackEnd::ProjectPartPch &&projectPartPch); void removeProjectPartPch(Utils::SmallStringView projectPartId); - void addPchToDatabase(const ClangBackEnd::ProjectPartPch &projectPartPch); - void removePchFromDatabase(const Utils::SmallStringView &projectPartId); - private: ClangBackEnd::ProjectPartPchs m_projectPartPchs; std::vector<PchManagerNotifierInterface*> m_notifiers; PchManagerConnectionClient *m_connectionClient=nullptr; - PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage; }; } // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/projectupdater.cpp b/src/plugins/clangpchmanager/projectupdater.cpp index 81d140d3f7..a3fbb6cb62 100644 --- a/src/plugins/clangpchmanager/projectupdater.cpp +++ b/src/plugins/clangpchmanager/projectupdater.cpp @@ -72,9 +72,10 @@ void ProjectUpdater::updateProjectParts(const std::vector<CppTools::ProjectPart void ProjectUpdater::removeProjectParts(const QStringList &projectPartIds) { - ClangBackEnd::RemoveProjectPartsMessage message{Utils::SmallStringVector(projectPartIds)}; + Utils::SmallStringVector sortedIds(projectPartIds); + std::sort(sortedIds.begin(), sortedIds.end()); - m_server.removeProjectParts(std::move(message)); + m_server.removeProjectParts(ClangBackEnd::RemoveProjectPartsMessage{std::move(sortedIds)}); } void ProjectUpdater::updateGeneratedFiles(ClangBackEnd::V2::FileContainers &&generatedFiles) diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index 7a7df8abe7..a628593b45 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -1069,7 +1069,8 @@ void ClearCasePlugin::diffActivity() return; } QString topLevel = state.topLevel(); - QString activity = QInputDialog::getText(0, tr("Enter Activity"), tr("Activity Name"), QLineEdit::Normal, m_activity); + QString activity = QInputDialog::getText(ICore::dialogParent(), tr("Enter Activity"), + tr("Activity Name"), QLineEdit::Normal, m_activity); if (activity.isEmpty()) return; QStringList versions = ccGetActivityVersions(topLevel, activity); @@ -1527,7 +1528,8 @@ bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName (fi.isWritable() || vcsStatus(absPath).status == FileStatus::Unknown)) Utils::runAsync(sync, QStringList(absPath)).waitForFinished(); if (vcsStatus(absPath).status == FileStatus::CheckedOut) { - QMessageBox::information(0, tr("ClearCase Checkout"), tr("File is already checked out.")); + QMessageBox::information(ICore::dialogParent(), tr("ClearCase Checkout"), + tr("File is already checked out.")); return true; } @@ -1912,7 +1914,8 @@ bool ClearCasePlugin::newActivity() QStringList args; args << QLatin1String("mkactivity") << QLatin1String("-f"); if (!m_settings.autoAssignActivityName) { - QString headline = QInputDialog::getText(0, tr("Activity Headline"), tr("Enter activity headline")); + QString headline = QInputDialog::getText(ICore::dialogParent(), tr("Activity Headline"), + tr("Enter activity headline")); if (headline.isEmpty()) return false; args << QLatin1String("-headline") << headline; diff --git a/src/plugins/texteditor/colorschemeedit.cpp b/src/plugins/texteditor/colorschemeedit.cpp index 5a6ecf654a..8049c191a3 100644 --- a/src/plugins/texteditor/colorschemeedit.cpp +++ b/src/plugins/texteditor/colorschemeedit.cpp @@ -278,6 +278,7 @@ void ColorSchemeEdit::updateForegroundControls() bool isVisible = formatDescription.showControl(FormatDescription::ShowForegroundControl); + m_ui->relativeForegroundHeadline->setEnabled(isVisible); m_ui->foregroundLabel->setVisible(isVisible); m_ui->foregroundToolButton->setVisible(isVisible); m_ui->eraseForegroundToolButton->setVisible(isVisible); @@ -296,6 +297,7 @@ void ColorSchemeEdit::updateBackgroundControls() bool isVisible = formatDescription.showControl(FormatDescription::ShowBackgroundControl); + m_ui->relativeBackgroundHeadline->setVisible(isVisible); m_ui->backgroundLabel->setVisible(isVisible); m_ui->backgroundToolButton->setVisible(isVisible); m_ui->eraseBackgroundToolButton->setVisible(isVisible); @@ -326,6 +328,14 @@ void ColorSchemeEdit::updateRelativeForegroundControls() m_ui->relativeForegroundSpacer2->setVisible(isVisible); m_ui->relativeForegroundSpacer3->setVisible(isVisible); + bool isEnabled = !m_readOnly && !format.foreground().isValid(); + + m_ui->relativeForegroundHeadline->setEnabled(isEnabled); + m_ui->foregroundSaturationLabel->setEnabled(isEnabled); + m_ui->foregroundLightnessLabel->setEnabled(isEnabled); + m_ui->foregroundSaturationSpinBox->setEnabled(isEnabled); + m_ui->foregroundLightnessSpinBox->setEnabled(isEnabled); + m_ui->foregroundSaturationSpinBox->setValue(format.relativeForegroundSaturation()); m_ui->foregroundLightnessSpinBox->setValue(format.relativeForegroundLightness()); } @@ -349,6 +359,14 @@ void ColorSchemeEdit::updateRelativeBackgroundControls() m_ui->relativeBackgroundSpacer2->setVisible(isVisible); m_ui->relativeBackgroundSpacer3->setVisible(isVisible); + bool isEnabled = !m_readOnly && !format.background().isValid(); + + m_ui->relativeBackgroundHeadline->setEnabled(isEnabled); + m_ui->backgroundSaturationLabel->setEnabled(isEnabled); + m_ui->backgroundLightnessLabel->setEnabled(isEnabled); + m_ui->backgroundSaturationSpinBox->setEnabled(isEnabled); + m_ui->backgroundLightnessSpinBox->setEnabled(isEnabled); + m_ui->backgroundSaturationSpinBox->setValue(format.relativeBackgroundSaturation()); m_ui->backgroundLightnessSpinBox->setValue(format.relativeBackgroundLightness()); } @@ -415,6 +433,8 @@ void ColorSchemeEdit::changeForeColor() m_scheme.formatFor(category).setForeground(newColor); m_formatsModel->emitDataChanged(index); } + + updateControls(); } void ColorSchemeEdit::changeBackColor() @@ -436,6 +456,8 @@ void ColorSchemeEdit::changeBackColor() if (index.row() == 0) setItemListBackground(newColor); } + + updateControls(); } void ColorSchemeEdit::eraseBackColor() @@ -451,6 +473,8 @@ void ColorSchemeEdit::eraseBackColor() m_scheme.formatFor(category).setBackground(newColor); m_formatsModel->emitDataChanged(index); } + + updateControls(); } void ColorSchemeEdit::eraseForeColor() @@ -466,6 +490,8 @@ void ColorSchemeEdit::eraseForeColor() m_scheme.formatFor(category).setForeground(newColor); m_formatsModel->emitDataChanged(index); } + + updateControls(); } void ColorSchemeEdit::changeRelativeForeColor() diff --git a/src/plugins/texteditor/fontsettingspage.h b/src/plugins/texteditor/fontsettingspage.h index ab507a4550..9f696b3ee8 100644 --- a/src/plugins/texteditor/fontsettingspage.h +++ b/src/plugins/texteditor/fontsettingspage.h @@ -58,36 +58,40 @@ public: ShowUnderlineControl = 0x8, ShowRelativeForegroundControl = 0x10, ShowRelativeBackgroundControl = 0x20, + ShowRelativeControls = ShowRelativeForegroundControl | ShowRelativeBackgroundControl, ShowFontUnderlineAndRelativeControls = ShowFontControls | ShowUnderlineControl - | ShowRelativeForegroundControl - | ShowRelativeBackgroundControl, - AllControls = 0xF, - AllControlsExceptUnderline = AllControls & ~ShowUnderlineControl, + | ShowRelativeControls, + ShowAllAbsoluteControls = ShowForegroundControl + | ShowBackgroundControl + | ShowFontControls + | ShowUnderlineControl, + ShowAllAbsoluteControlsExceptUnderline = ShowAllAbsoluteControls & ~ShowUnderlineControl, + ShowAllControls = ShowAllAbsoluteControls | ShowRelativeControls }; FormatDescription() = default; FormatDescription(TextStyle id, const QString &displayName, const QString &tooltipText, - ShowControls showControls = AllControls); + ShowControls showControls = ShowAllAbsoluteControls); FormatDescription(TextStyle id, const QString &displayName, const QString &tooltipText, const QColor &foreground, - ShowControls showControls = AllControls); + ShowControls showControls = ShowAllAbsoluteControls); FormatDescription(TextStyle id, const QString &displayName, const QString &tooltipText, const Format &format, - ShowControls showControls = AllControls); + ShowControls showControls = ShowAllAbsoluteControls); FormatDescription(TextStyle id, const QString &displayName, const QString &tooltipText, const QColor &underlineColor, const QTextCharFormat::UnderlineStyle underlineStyle, - ShowControls showControls = AllControls); + ShowControls showControls = ShowAllAbsoluteControls); TextStyle id() const { return m_id; } @@ -110,7 +114,7 @@ private: Format m_format; // Default format QString m_displayName; // Displayed name of the category QString m_tooltipText; // Description text for category - ShowControls m_showControls = AllControls; + ShowControls m_showControls = ShowAllAbsoluteControls; }; typedef std::vector<FormatDescription> FormatDescriptions; diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp index 0c02eb3cd1..f5cc088f22 100644 --- a/src/plugins/texteditor/texteditorsettings.cpp +++ b/src/plugins/texteditor/texteditorsettings.cpp @@ -103,7 +103,7 @@ TextEditorSettings::TextEditorSettings() p.color(QPalette::HighlightedText)); formatDescr.emplace_back(C_LINE_NUMBER, tr("Line Number"), tr("Line numbers located on the left side of the editor."), - FormatDescription::AllControlsExceptUnderline); + FormatDescription::ShowAllAbsoluteControlsExceptUnderline); formatDescr.emplace_back(C_SEARCH_RESULT, tr("Search Result"), tr("Highlighted search results inside the editor."), FormatDescription::ShowBackgroundControl); @@ -128,7 +128,7 @@ TextEditorSettings::TextEditorSettings() tr("Line number located on the left side of the " "editor where the cursor is placed in."), Qt::darkGray, - FormatDescription::AllControlsExceptUnderline); + FormatDescription::ShowAllAbsoluteControlsExceptUnderline); currentLineNumber.format().setBold(true); formatDescr.push_back(std::move(currentLineNumber)); @@ -168,6 +168,18 @@ TextEditorSettings::TextEditorSettings() functionFormat.setForeground(QColor(0, 103, 124)); formatDescr.emplace_back(C_FUNCTION, tr("Function"), tr("Name of a function."), functionFormat); + Format declarationFormat = Format::createMixinFormat(); + declarationFormat.setBold(true); + formatDescr.emplace_back(C_DECLARATION, + tr("Function Declaration"), + tr("Style adjustments to (function) declarations."), + declarationFormat, + FormatDescription::ShowAllControls); + formatDescr.emplace_back(C_FUNCTION_DEFINITION, + tr("Function Definition"), + tr("Name of function at its definition."), + Format::createMixinFormat(), + FormatDescription::ShowAllControls); functionFormat.setItalic(true); formatDescr.emplace_back(C_VIRTUAL_METHOD, tr("Virtual Function"), tr("Name of function declared as virtual."), @@ -229,11 +241,13 @@ TextEditorSettings::TextEditorSettings() formatDescr.emplace_back(C_OPERATOR, tr("Operator"), tr("Non user-defined language operators.\n" "To style user-defined operators, use Overloaded Operator."), - Format::createMixinFormat()); + Format::createMixinFormat(), + FormatDescription::ShowAllControls); formatDescr.emplace_back(C_OVERLOADED_OPERATOR, tr("Overloaded Operators"), tr("Calls and declarations of overloaded (user-defined) operators."), - Format::createMixinFormat()); + Format::createMixinFormat(), + FormatDescription::ShowAllControls); formatDescr.emplace_back(C_PREPROCESSOR, tr("Preprocessor"), tr("Preprocessor directives."), Qt::darkBlue); formatDescr.emplace_back(C_LABEL, tr("Label"), tr("Labels for goto statements."), @@ -301,43 +315,32 @@ TextEditorSettings::TextEditorSettings() tr("Underline color of error diagnostics."), QColor(255,0, 0), QTextCharFormat::SingleUnderline, - FormatDescription::ShowUnderlineControl); + FormatDescription::ShowAllControls); formatDescr.emplace_back(C_ERROR_CONTEXT, tr("Error Context"), tr("Underline color of the contexts of error diagnostics."), QColor(255,0, 0), QTextCharFormat::DotLine, - FormatDescription::ShowUnderlineControl); + FormatDescription::ShowAllControls); formatDescr.emplace_back(C_WARNING, tr("Warning"), tr("Underline color of warning diagnostics."), QColor(255, 190, 0), QTextCharFormat::SingleUnderline, - FormatDescription::ShowUnderlineControl); + FormatDescription::ShowAllControls); formatDescr.emplace_back(C_WARNING_CONTEXT, tr("Warning Context"), tr("Underline color of the contexts of warning diagnostics."), QColor(255, 190, 0), QTextCharFormat::DotLine, - FormatDescription::ShowUnderlineControl); - Format declarationFormat = Format::createMixinFormat(); - declarationFormat.setBold(true); - formatDescr.emplace_back(C_DECLARATION, - tr("Function Declaration"), - tr("Style adjustments to (function) declarations."), - declarationFormat, - FormatDescription::ShowFontUnderlineAndRelativeControls); - formatDescr.emplace_back(C_FUNCTION_DEFINITION, - tr("Function Definition"), - tr("Name of function at its definition."), - Format::createMixinFormat()); + FormatDescription::ShowAllControls); Format outputArgumentFormat = Format::createMixinFormat(); outputArgumentFormat.setItalic(true); formatDescr.emplace_back(C_OUTPUT_ARGUMENT, tr("Output Argument"), tr("Writable arguments of a function call."), outputArgumentFormat, - FormatDescription::ShowFontUnderlineAndRelativeControls); + FormatDescription::ShowAllControls); d->m_fontSettingsPage = new FontSettingsPage(formatDescr, Constants::TEXT_EDITOR_FONT_SETTINGS, diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp index d751ab0bd4..d510427081 100644 --- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp +++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp @@ -28,13 +28,16 @@ #include <environment.h> #include <generatedfiles.h> #include <pchcreator.h> -#include <pchgenerator.h> #include <pchmanagerserver.h> #include <pchmanagerclientproxy.h> +#include <precompiledheaderstorage.h> +#include <processormanager.h> #include <projectparts.h> +#include <projectpartqueue.h> #include <filepathcaching.h> #include <refactoringdatabaseinitializer.h> #include <sqlitedatabase.h> +#include <taskscheduler.h> #include <QCommandLineParser> #include <QCoreApplication> @@ -53,9 +56,9 @@ using ClangBackEnd::ClangPathWatcher; using ClangBackEnd::ConnectionServer; using ClangBackEnd::GeneratedFiles; using ClangBackEnd::PchCreator; -using ClangBackEnd::PchGenerator; using ClangBackEnd::PchManagerClientProxy; using ClangBackEnd::PchManagerServer; +using ClangBackEnd::PrecompiledHeaderStorage; using ClangBackEnd::ProjectParts; using ClangBackEnd::FilePathCache; @@ -121,6 +124,61 @@ QStringList processArguments(QCoreApplication &application) return parser.positionalArguments(); } +class PchCreatorManager final : public ClangBackEnd::ProcessorManager<ClangBackEnd::PchCreator> +{ +public: + using Processor = ClangBackEnd::PchCreator; + PchCreatorManager(const ClangBackEnd::GeneratedFiles &generatedFiles, + ClangBackEnd::Environment &environment, + Sqlite::Database &database, + PchManagerServer &pchManagerServer, + ClangBackEnd::ClangPathWatcherInterface &fileSystemWatcher) + : ProcessorManager(generatedFiles), + m_environment(environment), + m_database(database), + m_pchManagerServer(pchManagerServer), + m_fileSystemWatcher(fileSystemWatcher) + {} + +protected: + std::unique_ptr<ClangBackEnd::PchCreator> createProcessor() const override + { + return std::make_unique<PchCreator>(m_environment, + m_database, + *m_pchManagerServer.client(), + m_fileSystemWatcher); + } + +private: + ClangBackEnd::Environment &m_environment; + Sqlite::Database &m_database; + ClangBackEnd::PchManagerServer &m_pchManagerServer; + ClangBackEnd::ClangPathWatcherInterface &m_fileSystemWatcher; +}; + +struct Data // because we have a cycle dependency +{ + using TaskScheduler = ClangBackEnd::TaskScheduler<PchCreatorManager, ClangBackEnd::ProjectPartQueue::Task>; + + Data(const QString &databasePath, + const QString &pchsPath) + : database{Utils::PathString{databasePath}, 100000ms}, + environment{pchsPath} + {} + Sqlite::Database database; + ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; + ClangBackEnd::FilePathCaching filePathCache{database}; + ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher{filePathCache}; + ApplicationEnvironment environment; + ProjectParts projectParts; + GeneratedFiles generatedFiles; + PchCreatorManager pchCreatorManager{generatedFiles, environment, database, clangPchManagerServer, includeWatcher}; + PrecompiledHeaderStorage<> preCompiledHeaderStorage{database}; + TaskScheduler taskScheduler{pchCreatorManager, projectPartQueue, std::thread::hardware_concurrency()}; + ClangBackEnd::ProjectPartQueue projectPartQueue{taskScheduler, preCompiledHeaderStorage, database}; + PchManagerServer clangPchManagerServer{includeWatcher, projectPartQueue, projectParts, generatedFiles}; +}; + int main(int argc, char *argv[]) { try { @@ -138,25 +196,12 @@ int main(int argc, char *argv[]) const QString databasePath = arguments[1]; const QString pchsPath = arguments[2]; - Sqlite::Database database{Utils::PathString{databasePath}, 100000ms}; - ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; - ClangBackEnd::FilePathCaching filePathCache{database}; - ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher(filePathCache); - ApplicationEnvironment environment{pchsPath}; - PchGenerator<QProcess> pchGenerator(environment); - GeneratedFiles generatedFiles; - PchCreator pchCreator(environment, filePathCache, generatedFiles); - pchCreator.setGenerator(&pchGenerator); - ProjectParts projectParts; - PchManagerServer clangPchManagerServer(includeWatcher, - pchCreator, - projectParts, - generatedFiles); - includeWatcher.setNotifier(&clangPchManagerServer); - pchGenerator.setNotifier(&clangPchManagerServer); + Data data{databasePath, pchsPath}; + + data.includeWatcher.setNotifier(&data.clangPchManagerServer); ConnectionServer<PchManagerServer, PchManagerClientProxy> connectionServer; - connectionServer.setServer(&clangPchManagerServer); + connectionServer.setServer(&data.clangPchManagerServer); connectionServer.start(connectionName); return application.exec(); diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri index 9556f50cd1..c6cf965992 100644 --- a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri +++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri @@ -2,7 +2,8 @@ INCLUDEPATH += $$PWD SOURCES += \ $$PWD/pchmanagerserver.cpp \ - $$PWD/projectparts.cpp + $$PWD/projectparts.cpp \ + $$PWD/projectpartqueue.cpp HEADERS += \ $$PWD/pchmanagerserver.h \ @@ -12,9 +13,15 @@ HEADERS += \ $$PWD/projectparts.h \ $$PWD/pchcreatorinterface.h \ $$PWD/projectpartsinterface.h \ - $$PWD/pchgenerator.h \ - $$PWD/pchgeneratornotifierinterface.h \ - $$PWD/pchgeneratorinterface.h + $$PWD/projectpartqueue.h \ + $$PWD/queueinterface.h \ + $$PWD/projectpartqueueinterface.h \ + $$PWD/processormanagerinterface.h \ + $$PWD/processorinterface.h \ + $$PWD/taskscheduler.h \ + $$PWD/taskschedulerinterface.h \ + $$PWD/precompiledheaderstorage.h \ + $$PWD/precompiledheaderstorageinterface.h !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ @@ -26,5 +33,6 @@ HEADERS += \ $$PWD/collectincludestoolaction.h \ $$PWD/collectincludesaction.h \ $$PWD/collectincludespreprocessorcallbacks.h \ - $$PWD/pchcreator.h + $$PWD/pchcreator.h \ + $$PWD/processormanager.h } diff --git a/src/tools/clangpchmanagerbackend/source/collectincludesaction.h b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h index 923cf5bfc0..d55559b41e 100644 --- a/src/tools/clangpchmanagerbackend/source/collectincludesaction.h +++ b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h @@ -41,7 +41,7 @@ class CollectIncludesAction final : public clang::PreprocessOnlyAction public: CollectIncludesAction(FilePathIds &includeIds, FilePathIds &topIncludeIds, - FilePathCachingInterface &filePathCache, + const FilePathCachingInterface &filePathCache, std::vector<uint> &excludedIncludeUID, std::vector<uint> &alreadyIncludedFileUIDs) : m_includeIds(includeIds), @@ -56,12 +56,10 @@ public: { if (clang::PreprocessOnlyAction::BeginSourceFileAction(compilerInstance)) { auto &preprocessor = compilerInstance.getPreprocessor(); - auto &headerSearch = preprocessor.getHeaderSearchInfo(); preprocessor.SetSuppressIncludeNotFoundError(true); auto macroPreprocessorCallbacks = new CollectIncludesPreprocessorCallbacks( - headerSearch, m_includeIds, m_topIncludeIds, m_filePathCache, @@ -85,7 +83,7 @@ public: private: FilePathIds &m_includeIds; FilePathIds &m_topIncludeIds; - FilePathCachingInterface &m_filePathCache; + const FilePathCachingInterface &m_filePathCache; std::vector<uint> &m_excludedIncludeUID; std::vector<uint> &m_alreadyIncludedFileUIDs; }; diff --git a/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h index 645d87e91d..2a6d0a54d8 100644 --- a/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h +++ b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h @@ -48,15 +48,13 @@ namespace ClangBackEnd { class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks { public: - CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch, - FilePathIds &includeIds, + CollectIncludesPreprocessorCallbacks(FilePathIds &includeIds, FilePathIds &topIncludeIds, - FilePathCachingInterface &filePathCache, + const FilePathCachingInterface &filePathCache, const std::vector<uint> &excludedIncludeUID, std::vector<uint> &alreadyIncludedFileUIDs, clang::SourceManager &sourceManager) - : m_headerSearch(headerSearch), - m_includeIds(includeIds), + : m_includeIds(includeIds), m_topIncludeIds(topIncludeIds), m_filePathCache(filePathCache), m_excludedIncludeUID(excludedIncludeUID), @@ -159,10 +157,9 @@ public: } private: - clang::HeaderSearch &m_headerSearch; FilePathIds &m_includeIds; FilePathIds &m_topIncludeIds; - FilePathCachingInterface &m_filePathCache; + const FilePathCachingInterface &m_filePathCache; const std::vector<uint> &m_excludedIncludeUID; std::vector<uint> &m_alreadyIncludedFileUIDs; clang::SourceManager &m_sourceManager; diff --git a/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h index e5c30829fa..a9c6e9717e 100644 --- a/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h +++ b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h @@ -39,7 +39,7 @@ class CollectIncludesToolAction final : public clang::tooling::FrontendActionFac public: CollectIncludesToolAction(FilePathIds &includeIds, FilePathIds &topIncludeIds, - FilePathCachingInterface &filePathCache, + const FilePathCachingInterface &filePathCache, const Utils::PathStringVector &excludedIncludes) : m_includeIds(includeIds), m_topIncludeIds(topIncludeIds), @@ -93,7 +93,7 @@ private: std::vector<uint> m_excludedIncludeUIDs; FilePathIds &m_includeIds; FilePathIds &m_topIncludeIds; - FilePathCachingInterface &m_filePathCache; + const FilePathCachingInterface &m_filePathCache; const Utils::PathStringVector &m_excludedIncludes; }; diff --git a/src/tools/clangpchmanagerbackend/source/includecollector.cpp b/src/tools/clangpchmanagerbackend/source/includecollector.cpp index 3c93de82b2..6be1533353 100644 --- a/src/tools/clangpchmanagerbackend/source/includecollector.cpp +++ b/src/tools/clangpchmanagerbackend/source/includecollector.cpp @@ -33,7 +33,7 @@ namespace ClangBackEnd { -IncludeCollector::IncludeCollector(FilePathCachingInterface &filePathCache) +IncludeCollector::IncludeCollector(const FilePathCachingInterface &filePathCache) : m_filePathCache(filePathCache) { } diff --git a/src/tools/clangpchmanagerbackend/source/includecollector.h b/src/tools/clangpchmanagerbackend/source/includecollector.h index fc3c1a5991..30dd89d470 100644 --- a/src/tools/clangpchmanagerbackend/source/includecollector.h +++ b/src/tools/clangpchmanagerbackend/source/includecollector.h @@ -34,7 +34,7 @@ namespace ClangBackEnd { class IncludeCollector : public ClangTool { public: - IncludeCollector(FilePathCachingInterface &filePathCache); + IncludeCollector(const FilePathCachingInterface &filePathCache); void collectIncludes(); @@ -48,7 +48,7 @@ private: FilePathIds m_includeIds; FilePathIds m_topIncludeIds; Utils::SmallStringVector m_directories; - FilePathCachingInterface &m_filePathCache; + const FilePathCachingInterface &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp index fb7ccaae53..e02f563efe 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp @@ -29,39 +29,21 @@ #include "includecollector.h" #include "pchnotcreatederror.h" +#include <clangpathwatcherinterface.h> #include <filepathcachinginterface.h> #include <generatedfiles.h> +#include <pchmanagerclientinterface.h> +#include <precompiledheadersupdatedmessage.h> #include <projectpartpch.h> #include <QCryptographicHash> #include <QDateTime> #include <QFile> +#include <QProcess> #include <QTemporaryFile> namespace ClangBackEnd { -PchCreator::PchCreator(Environment &environment, - FilePathCachingInterface &filePathCache, - const GeneratedFiles &generatedFiles) - : m_generatedFiles(generatedFiles), - m_environment(environment), - m_filePathCache(filePathCache) -{ -} - -PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts, - Environment &environment, - FilePathCachingInterface &filePathCache, - PchGeneratorInterface *pchGenerator, - const GeneratedFiles &generatedFiles) - : m_projectParts(std::move(projectsParts)), - m_generatedFiles(generatedFiles), - m_environment(environment), - m_filePathCache(filePathCache), - m_pchGenerator(pchGenerator) -{ -} - namespace { template <typename Source, typename Target> @@ -76,16 +58,6 @@ void append(Target &target, const Source &source) target.push_back(ValueType(std::move(entry))); } -template <typename Source, - typename Target> -void append(Target &target, Source &source) -{ - target.reserve(target.size() + source.size()); - - for (auto &&entry : source) - target.emplace_back(entry); -} - void appendFilePathId(Utils::PathStringVector &target, const ClangBackEnd::FilePathIds &source, const ClangBackEnd::FilePathCachingInterface &filePathCache) @@ -94,51 +66,6 @@ void appendFilePathId(Utils::PathStringVector &target, target.emplace_back(filePathCache.filePath(id).path()); } -template <typename GetterFunction> -std::size_t globalCount(const V2::ProjectPartContainers &projectsParts, - GetterFunction getterFunction) -{ - auto sizeFunction = [&] (std::size_t size, const V2::ProjectPartContainer &projectContainer) { - return size + getterFunction(projectContainer).size(); - }; - - return std::accumulate(projectsParts.begin(), - projectsParts.end(), - std::size_t(0), - sizeFunction); -} - -template <typename Container, - typename GetterFunction> -void generateGlobal(Container &entries, - const V2::ProjectPartContainers &projectsParts, - GetterFunction getterFunction) -{ - entries.reserve(entries.capacity() + globalCount(projectsParts, getterFunction)); - - for (const V2::ProjectPartContainer &projectPart : projectsParts) { - auto &&projectPartPaths = getterFunction(projectPart); - - append(entries, projectPartPaths); - }; -} - -template <typename Container, - typename GetterFunction> -Utils::PathStringVector generateGlobal( - const V2::ProjectPartContainers &projectsParts, - GetterFunction getterFunction, - std::size_t prereserve = 0) -{ - Container entries; - entries.reserve(prereserve); - - generateGlobal(entries, projectsParts, getterFunction); - - return entries; -} - - Utils::PathStringVector generatedFilePaths(const V2::FileContainers &generaredFiles) { Utils::PathStringVector generaredFilePaths; @@ -152,114 +79,6 @@ Utils::PathStringVector generatedFilePaths(const V2::FileContainers &generaredFi } -Utils::PathStringVector PchCreator::generateGlobalHeaderPaths() const -{ - auto includeFunction = [&] (const V2::ProjectPartContainer &projectPart) { - return m_filePathCache.filePaths(projectPart.headerPathIds); - }; - - Utils::PathStringVector headerPaths = generateGlobal<Utils::PathStringVector>(m_projectParts, - includeFunction, - m_generatedFiles.fileContainers().size()); - - Utils::PathStringVector generatedPath = generatedFilePaths(m_generatedFiles.fileContainers()); - - headerPaths.insert(headerPaths.end(), - std::make_move_iterator(generatedPath.begin()), - std::make_move_iterator(generatedPath.end())); - - return headerPaths; -} - -Utils::PathStringVector PchCreator::generateGlobalSourcePaths() const -{ - auto sourceFunction = [&] (const V2::ProjectPartContainer &projectPart) { - return m_filePathCache.filePaths(projectPart.sourcePathIds); - }; - - return generateGlobal<Utils::PathStringVector>(m_projectParts, sourceFunction); -} - -Utils::PathStringVector PchCreator::generateGlobalHeaderAndSourcePaths() const -{ - const auto &sourcePaths = generateGlobalSourcePaths(); - auto includePaths = generateGlobalHeaderPaths(); - - append(includePaths, sourcePaths); - - return includePaths; -} - -Utils::SmallStringVector PchCreator::generateGlobalArguments() const -{ - Utils::SmallStringVector arguments; - - auto argumentFunction = [] (const V2::ProjectPartContainer &projectPart) - -> const Utils::SmallStringVector & { - return projectPart.arguments; - }; - - generateGlobal(arguments, m_projectParts, argumentFunction); - - return arguments; -} - -Utils::SmallStringVector PchCreator::generateGlobalCommandLine() const -{ - Utils::SmallStringVector commandLine; - commandLine.emplace_back(m_environment.clangCompilerPath()); - - auto argumentFunction = [] (const V2::ProjectPartContainer &projectPart) - -> const Utils::SmallStringVector & { - return projectPart.arguments; - }; - - generateGlobal(commandLine, m_projectParts, argumentFunction); - - return commandLine; -} - -Utils::SmallStringVector PchCreator::generateGlobalPchCompilerArguments() const -{ - Utils::SmallStringVector arguments; - arguments.reserve(5); - - arguments.emplace_back("-x"); - arguments.emplace_back("c++-header"); - arguments.emplace_back("-Xclang"); - arguments.emplace_back("-emit-pch"); - arguments.emplace_back("-o"); - arguments.emplace_back(generateGlobalPchFilePath()); - arguments.emplace_back(generateGlobalPchHeaderFilePath()); - - return arguments; -} - -Utils::SmallStringVector PchCreator::generateGlobalClangCompilerArguments() const -{ - auto compilerArguments = generateGlobalArguments(); - const auto pchArguments = generateGlobalPchCompilerArguments(); - - append(compilerArguments, pchArguments); - - return compilerArguments; -} - -FilePathIds PchCreator::generateGlobalPchIncludeIds() const -{ - IncludeCollector collector(m_filePathCache); - - collector.setExcludedIncludes(generateGlobalSourcePaths()); - - collector.addFiles(generateGlobalHeaderAndSourcePaths(), generateGlobalCommandLine()); - - collector.addUnsavedFiles(m_generatedFiles.fileContainers()); - - collector.collectIncludes(); - - return collector.takeIncludeIds(); -} - namespace { std::size_t contentSize(const FilePaths &includes) @@ -286,28 +105,19 @@ Utils::SmallString PchCreator::generatePchIncludeFileContent(const FilePathIds & return fileContent; } -Utils::SmallString PchCreator::generateGlobalPchHeaderFileContent() const -{ - return generatePchIncludeFileContent(generateGlobalPchIncludeIds()); -} -std::unique_ptr<QFile> PchCreator::generateGlobalPchHeaderFile() +bool PchCreator::generatePch(Utils::SmallStringVector &&compilerArguments) { - return generateFileWithContent(generateGlobalPchHeaderFilePath(), - generateGlobalPchHeaderFileContent()); -} + QProcess process; -void PchCreator::generatePch(Utils::SmallStringVector &&compilerArguments, - ProjectPartPch &&projectPartPch) -{ - m_pchGenerator->startTask(std::move(compilerArguments), std::move(projectPartPch)); -} + process.setProcessChannelMode(QProcess::ForwardedChannels); + process.setArguments(QStringList(compilerArguments)); + process.setProgram(QString(m_environment.clangCompilerPath())); -void PchCreator::generateGlobalPch() -{ - generateGlobalPchHeaderFile(); + process.start(); + process.waitForFinished(300000); - generatePch(generateGlobalClangCompilerArguments(), ProjectPartPch()); + return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; } QStringList PchCreator::convertToQStringList(const Utils::SmallStringVector &compilerArguments) @@ -324,52 +134,13 @@ namespace { void hashProjectPart(QCryptographicHash &hash, const V2::ProjectPartContainer &projectPart) { const auto &projectPartId = projectPart.projectPartId; - hash.addData(projectPartId.data(), projectPartId.size()); + hash.addData(projectPartId.data(), int(projectPartId.size())); for (const auto &argument : projectPart.arguments) - hash.addData(argument.data(), argument.size()); + hash.addData(argument.data(), int(argument.size())); } } -QByteArray PchCreator::globalProjectHash() const -{ - QCryptographicHash hash(QCryptographicHash::Sha1); - - for (const auto &projectPart : m_projectParts) - hashProjectPart(hash, projectPart); - - auto result = hash.result(); - - return result.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); -} - -Utils::SmallString PchCreator::generateGlobalPchFilePathWithoutExtension() const -{ - QByteArray fileName = m_environment.pchBuildDirectory().toUtf8(); - fileName += '/'; - fileName += globalProjectHash(); - - return Utils::SmallString::fromQByteArray(fileName); -} - -Utils::SmallString PchCreator::generateGlobalPchHeaderFilePath() const -{ - Utils::SmallString filePath = generateGlobalPchFilePathWithoutExtension(); - - filePath += ".h"; - - return filePath; -} - -Utils::SmallString PchCreator::generateGlobalPchFilePath() const -{ - Utils::SmallString filePath = generateGlobalPchFilePathWithoutExtension(); - - filePath += ".pch"; - - return filePath; -} - Utils::SmallStringVector PchCreator::generateProjectPartCommandLine( const V2::ProjectPartContainer &projectPart) const { @@ -399,7 +170,7 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaders( const V2::ProjectPartContainer &projectPart) const { Utils::PathStringVector headerPaths; - headerPaths.reserve(projectPart.headerPathIds.size() + m_generatedFiles.fileContainers().size()); + headerPaths.reserve(projectPart.headerPathIds.size() + m_unsavedFiles.size()); std::transform(projectPart.headerPathIds.begin(), projectPart.headerPathIds.end(), @@ -408,7 +179,7 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaders( return m_filePathCache.filePath(filePathId); }); - Utils::PathStringVector generatedPath = generatedFilePaths(m_generatedFiles.fileContainers()); + Utils::PathStringVector generatedPath = generatedFilePaths(m_unsavedFiles); std::copy(std::make_move_iterator(generatedPath.begin()), std::make_move_iterator(generatedPath.end()), @@ -484,7 +255,7 @@ std::pair<FilePathIds,FilePathIds> PchCreator::generateProjectPartPchIncludes( {}, arguments); - collector.addUnsavedFiles(m_generatedFiles.fileContainers()); + collector.addUnsavedFiles(m_unsavedFiles); collector.collectIncludes(); @@ -549,35 +320,68 @@ IdPaths PchCreator::generateProjectPartPch(const V2::ProjectPartContainer &proje auto pchFilePath = generateProjectPartPchFilePath(projectPart); generateFileWithContent(pchIncludeFilePath, content); - generatePch(generateProjectPartClangCompilerArguments(projectPart), - {projectPart.projectPartId.clone(), std::move(pchFilePath), lastModified}); + bool success = generatePch(generateProjectPartClangCompilerArguments(projectPart)); + + m_projectPartPch.projectPartId = projectPart.projectPartId; + + if (success) { + m_projectPartPch.pchPath = std::move(pchFilePath); + m_projectPartPch.lastModified = lastModified; + } return {projectPart.projectPartId.clone(), std::move(allExternalIncludes)}; } -void PchCreator::generatePchs() +void PchCreator::generatePch(const V2::ProjectPartContainer &projectPart) { - for (const V2::ProjectPartContainer &projectPart : m_projectParts) { - auto includePaths = generateProjectPartPch(projectPart); - m_projectsIncludeIds.push_back(std::move(includePaths)); - } + m_projectIncludeIds = generateProjectPartPch(projectPart); +} + +IdPaths PchCreator::takeProjectIncludes() +{ + return std::move(m_projectIncludeIds); +} + +const ProjectPartPch &PchCreator::projectPartPch() +{ + return m_projectPartPch; +} + +void PchCreator::setUnsavedFiles(const V2::FileContainers &fileContainers) +{ + m_unsavedFiles = fileContainers; } -void PchCreator::generatePchs(V2::ProjectPartContainers &&projectsParts) +void PchCreator::setIsUsed(bool isUsed) { - m_projectParts = std::move(projectsParts); + m_isUsed = isUsed; +} + +bool PchCreator::isUsed() const +{ + return m_isUsed; +} - generatePchs(); +void PchCreator::clear() +{ + m_projectPartPch = ProjectPartPch{}; + m_projectIncludeIds = IdPaths{}; +} + +void PchCreator::doInMainThreadAfterFinished() +{ + m_pchManagerClient.precompiledHeadersUpdated(ProjectPartPchs{m_projectPartPch}); + m_fileSystemWatcher.updateIdPaths({takeProjectIncludes()}); } -std::vector<IdPaths> PchCreator::takeProjectsIncludes() +const IdPaths &PchCreator::projectIncludes() const { - return std::move(m_projectsIncludeIds); + return m_projectIncludeIds; } -void PchCreator::setGenerator(PchGeneratorInterface *pchGenerator) +const FilePathCaching &PchCreator::filePathCache() { - m_pchGenerator = pchGenerator; + return m_filePathCache; } std::unique_ptr<QFile> PchCreator::generateFileWithContent( diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.h b/src/tools/clangpchmanagerbackend/source/pchcreator.h index 65425296b6..b3e0dcde56 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreator.h +++ b/src/tools/clangpchmanagerbackend/source/pchcreator.h @@ -27,10 +27,9 @@ #include "pchcreatorinterface.h" -#include "pchgeneratorinterface.h" #include "idpaths.h" -#include <filepathcachingfwd.h> +#include <filepathcaching.h> #include <projectpartpch.h> #include <projectpartcontainerv2.h> @@ -44,50 +43,40 @@ namespace ClangBackEnd { class Environment; class GeneratedFiles; +class PchManagerClientInterface; +class ClangPathWatcherInterface; class PchCreator final : public PchCreatorInterface { public: PchCreator(Environment &environment, - FilePathCachingInterface &filePathCache, - const GeneratedFiles &generatedFiles); - PchCreator(V2::ProjectPartContainers &&projectsParts, - Environment &environment, - FilePathCachingInterface &filePathCache, - PchGeneratorInterface *pchGenerator, - const GeneratedFiles &generatedFiles); - - void generatePchs(V2::ProjectPartContainers &&projectsParts) override; - std::vector<IdPaths> takeProjectsIncludes() override; - - void setGenerator(PchGeneratorInterface *pchGenerator); - -unittest_public: - Utils::PathStringVector generateGlobalHeaderPaths() const; - Utils::PathStringVector generateGlobalSourcePaths() const; - Utils::PathStringVector generateGlobalHeaderAndSourcePaths() const; - Utils::SmallStringVector generateGlobalArguments() const; - Utils::SmallStringVector generateGlobalCommandLine() const; - Utils::SmallStringVector generateGlobalPchCompilerArguments() const; - Utils::SmallStringVector generateGlobalClangCompilerArguments() const; - - FilePathIds generateGlobalPchIncludeIds() const; + Sqlite::Database &database, + PchManagerClientInterface &pchManagerClient, + ClangPathWatcherInterface &fileSystemWatcher) + : m_filePathCache(database), + m_environment(environment), + m_pchManagerClient(pchManagerClient), + m_fileSystemWatcher(fileSystemWatcher) + { + } + + void generatePch(const V2::ProjectPartContainer &projectsPart) override; + IdPaths takeProjectIncludes() override; + const ProjectPartPch &projectPartPch() override; + void setUnsavedFiles(const V2::FileContainers &fileContainers) override; + void setIsUsed(bool isUsed) override; + bool isUsed() const override; + void clear() override; + void doInMainThreadAfterFinished() override; + + const IdPaths &projectIncludes() const; + const FilePathCaching &filePathCache(); Utils::SmallString generatePchIncludeFileContent(const FilePathIds &includeIds) const; - Utils::SmallString generateGlobalPchHeaderFileContent() const; - std::unique_ptr<QFile> generateGlobalPchHeaderFile(); - void generatePch(Utils::SmallStringVector &&commandLineArguments, - ProjectPartPch &&projectPartPch); - void generateGlobalPch(); - - Utils::SmallString globalPchContent() const; + bool generatePch(Utils::SmallStringVector &&commandLineArguments); static QStringList convertToQStringList(const Utils::SmallStringVector &convertToQStringList); - Utils::SmallString generateGlobalPchFilePathWithoutExtension() const; - Utils::SmallString generateGlobalPchHeaderFilePath() const; - Utils::SmallString generateGlobalPchFilePath() const; - Utils::SmallStringVector generateProjectPartCommandLine( const V2::ProjectPartContainer &projectPart) const; Utils::SmallString generateProjectPartPchFilePathWithoutExtension( @@ -116,20 +105,18 @@ unittest_public: const Utils::SmallString &filePath, const Utils::SmallString &content); - void generatePchs(); - private: static QByteArray projectPartHash(const V2::ProjectPartContainer &projectPart); - QByteArray globalProjectHash() const; private: - V2::ProjectPartContainers m_projectParts; - std::vector<ProjectPartPch> m_projectPartPchs; - std::vector<IdPaths> m_projectsIncludeIds; - const GeneratedFiles &m_generatedFiles; + ProjectPartPch m_projectPartPch; + IdPaths m_projectIncludeIds; + FilePathCaching m_filePathCache; + V2::FileContainers m_unsavedFiles; Environment &m_environment; - FilePathCachingInterface &m_filePathCache; - PchGeneratorInterface *m_pchGenerator = nullptr; + PchManagerClientInterface &m_pchManagerClient; + ClangPathWatcherInterface &m_fileSystemWatcher; + bool m_isUsed = false; }; } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h b/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h index dd33176519..c3098577f7 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h +++ b/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h @@ -27,21 +27,23 @@ #include "idpaths.h" #include "projectpartpch.h" +#include "processorinterface.h" #include <filecontainerv2.h> #include <projectpartcontainerv2.h> namespace ClangBackEnd { -class PchCreatorInterface +class PchCreatorInterface : public ProcessorInterface { public: PchCreatorInterface() = default; PchCreatorInterface(const PchCreatorInterface &) = delete; PchCreatorInterface &operator=(const PchCreatorInterface &) = delete; - virtual void generatePchs(V2::ProjectPartContainers &&projectsParts) = 0; - virtual std::vector<IdPaths> takeProjectsIncludes() = 0; + virtual void generatePch(const V2::ProjectPartContainer &projectsPart) = 0; + virtual IdPaths takeProjectIncludes() = 0; + virtual const ProjectPartPch &projectPartPch() = 0; protected: ~PchCreatorInterface() = default; diff --git a/src/tools/clangpchmanagerbackend/source/pchgenerator.h b/src/tools/clangpchmanagerbackend/source/pchgenerator.h deleted file mode 100644 index 144f21bffa..0000000000 --- a/src/tools/clangpchmanagerbackend/source/pchgenerator.h +++ /dev/null @@ -1,165 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "environment.h" -#include "pchgeneratorinterface.h" -#include "pchgeneratornotifierinterface.h" - -#include <projectpartpch.h> - -#include <QProcess> - -#include <queue> - -namespace ClangBackEnd { - -template <typename Process> -class PchGenerator final : public PchGeneratorInterface -{ -public: - PchGenerator(Environment &environment, - PchGeneratorNotifierInterface *notifier=nullptr) - : m_environment(environment), - m_notifier(notifier) - { - } - - ~PchGenerator() - { - cleanupAllProcesses(); - } - - void startTask(Utils::SmallStringVector &&compilerArguments, ProjectPartPch &&projectPartPch) override - { - addTask(std::move(compilerArguments), std::move(projectPartPch)); - } - - void setNotifier(PchGeneratorNotifierInterface *notifier) - { - m_notifier = notifier; - } - -unittest_public: - Process *addTask(Utils::SmallStringVector &&compilerArguments, ProjectPartPch &&projectPartPch) - { - auto process = std::make_unique<Process>(); - Process *processPointer = process.get(); - - process->setProcessChannelMode(QProcess::ForwardedChannels); - process->setArguments(QStringList(compilerArguments)); - process->setProgram(QString(m_environment.clangCompilerPath())); - - connectProcess(processPointer, std::move(projectPartPch)); - - if (!deferProcess()) - startProcess(std::move(process)); - else - m_deferredProcesses.push(std::move(process)); - - return processPointer; - } - - void connectProcess(Process *process, ProjectPartPch &&projectPartPch) - { - auto finishedCallback = [=,projectPartPch=std::move(projectPartPch)] (int exitCode, QProcess::ExitStatus exitStatus) { - deleteProcess(process); - activateNextDeferredProcess(); - m_notifier->taskFinished(generateTaskFinishStatus(exitCode, exitStatus), projectPartPch); - }; - - QObject::connect(process, - static_cast<void (Process::*)(int, QProcess::ExitStatus)>(&Process::finished), - std::move(finishedCallback)); - } - - void startProcess(std::unique_ptr<Process> &&process) - { - process->start(); - m_runningProcesses.push_back(std::move(process)); - } - - const std::vector<std::unique_ptr<Process>> &runningProcesses() const - { - return m_runningProcesses; - } - - const std::queue<std::unique_ptr<Process>> &deferredProcesses() const - { - return m_deferredProcesses; - } - - void deleteProcess(Process *process) - { - auto found = std::find_if(m_runningProcesses.begin(), - m_runningProcesses.end(), - [=] (const std::unique_ptr<Process> &entry) { - return entry.get() == process; - }); - - if (found != m_runningProcesses.end()) { - std::unique_ptr<Process> avoidDoubleDeletedProcess = std::move(*found); - m_runningProcesses.erase(found); - } - } - - void cleanupAllProcesses() - { - std::vector<std::unique_ptr<Process>> runningProcesses = std::move(m_runningProcesses); - std::queue<std::unique_ptr<Process>> deferredProcesses = std::move(m_deferredProcesses); - } - - static TaskFinishStatus generateTaskFinishStatus(int exitCode, QProcess::ExitStatus exitStatus) - { - if (exitCode != 0 || exitStatus != QProcess::NormalExit) - return TaskFinishStatus::Unsuccessfully; - else - return TaskFinishStatus::Successfully; - } - - bool deferProcess() const - { - return m_environment.hardwareConcurrency() <= m_runningProcesses.size(); - } - - void activateNextDeferredProcess() - { - if (!m_deferredProcesses.empty()) { - std::unique_ptr<Process> process = std::move(m_deferredProcesses.front()); - m_deferredProcesses.pop(); - - startProcess(std::move(process)); - } - } - -private: - std::vector<std::unique_ptr<Process>> m_runningProcesses; - std::queue<std::unique_ptr<Process>> m_deferredProcesses; - Environment &m_environment; - PchGeneratorNotifierInterface *m_notifier=nullptr; -}; - -} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp index e165365d30..7ce2e553a2 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp @@ -27,6 +27,7 @@ #include <pchmanagerclientinterface.h> #include <precompiledheadersupdatedmessage.h> +#include <projectpartqueue.h> #include <removegeneratedfilesmessage.h> #include <removeprojectpartsmessage.h> #include <updategeneratedfilesmessage.h> @@ -39,11 +40,11 @@ namespace ClangBackEnd { PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, - PchCreatorInterface &pchCreator, + ProjectPartQueueInterface &projectPartQueue, ProjectPartsInterface &projectParts, GeneratedFilesInterface &generatedFiles) : m_fileSystemWatcher(fileSystemWatcher), - m_pchCreator(pchCreator), + m_projectPartQueue(projectPartQueue), m_projectParts(projectParts), m_generatedFiles(generatedFiles) { @@ -58,9 +59,7 @@ void PchManagerServer::end() void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message) { - m_pchCreator.generatePchs(m_projectParts.update(message.takeProjectsParts())); - - m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes()); + m_projectPartQueue.addProjectParts(m_projectParts.update(message.takeProjectsParts())); } void PchManagerServer::removeProjectParts(RemoveProjectPartsMessage &&message) @@ -68,6 +67,8 @@ void PchManagerServer::removeProjectParts(RemoveProjectPartsMessage &&message) m_fileSystemWatcher.removeIds(message.projectsPartIds); m_projectParts.remove(message.projectsPartIds); + + m_projectPartQueue.removeProjectParts(message.projectsPartIds); } void PchManagerServer::updateGeneratedFiles(UpdateGeneratedFilesMessage &&message) @@ -82,19 +83,11 @@ void PchManagerServer::removeGeneratedFiles(RemoveGeneratedFilesMessage &&messag void PchManagerServer::pathsWithIdsChanged(const Utils::SmallStringVector &ids) { - m_pchCreator.generatePchs(m_projectParts.projects(ids)); - - m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes()); + m_projectPartQueue.addProjectParts(m_projectParts.projects(ids)); } void PchManagerServer::pathsChanged(const FilePathIds &/*filePathIds*/) { } -void PchManagerServer::taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) -{ - if (status == TaskFinishStatus::Successfully) - client()->precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage({projectPartPch.clone()})); -} - } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h index 717ba03359..66b6c85e99 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h @@ -28,7 +28,6 @@ #include "clangpathwatcherinterface.h" #include "clangpathwatchernotifier.h" #include "pchcreatorinterface.h" -#include "pchgeneratornotifierinterface.h" #include "pchmanagerserverinterface.h" #include "projectpartsinterface.h" @@ -38,16 +37,16 @@ namespace ClangBackEnd { class SourceRangesAndDiagnosticsForQueryMessage; +class ProjectPartQueueInterface; class PchManagerServer : public PchManagerServerInterface, public ClangPathWatcherNotifier, - public PchGeneratorNotifierInterface, public IpcClientProvider<PchManagerClientInterface> { public: PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, - PchCreatorInterface &pchCreator, + ProjectPartQueueInterface &projectPartQueue, ProjectPartsInterface &projectParts, GeneratedFilesInterface &generatedFiles); @@ -59,11 +58,10 @@ public: void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override; void pathsChanged(const FilePathIds &filePathIds) override; - void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override; private: ClangPathWatcherInterface &m_fileSystemWatcher; - PchCreatorInterface &m_pchCreator; + ProjectPartQueueInterface &m_projectPartQueue; ProjectPartsInterface &m_projectParts; GeneratedFilesInterface &m_generatedFiles; }; diff --git a/src/plugins/clangpchmanager/precompiledheaderstorage.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h index 4ad57e980a..94c454231e 100644 --- a/src/plugins/clangpchmanager/precompiledheaderstorage.h +++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h @@ -32,7 +32,7 @@ #include <utils/smallstringview.h> -namespace ClangPchManager { +namespace ClangBackEnd { template<typename Database=Sqlite::Database> class PrecompiledHeaderStorage final : public PrecompiledHeaderStorageInterface diff --git a/src/plugins/clangpchmanager/precompiledheaderstorageinterface.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h index 1c834acbd3..9ff6e1efe2 100644 --- a/src/plugins/clangpchmanager/precompiledheaderstorageinterface.h +++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h @@ -27,7 +27,7 @@ #include <utils/smallstringview.h> -namespace ClangPchManager { +namespace ClangBackEnd { class PrecompiledHeaderStorageInterface { @@ -47,4 +47,4 @@ protected: ~PrecompiledHeaderStorageInterface() = default; }; -} // namespace ClangPchManager +} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/processorinterface.h b/src/tools/clangpchmanagerbackend/source/processorinterface.h new file mode 100644 index 0000000000..444c6c6ddb --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/processorinterface.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <filecontainerv2.h> + +namespace ClangBackEnd { + +class ProcessorInterface +{ +public: + ProcessorInterface() = default; + virtual ~ProcessorInterface() = default; + ProcessorInterface(const ProcessorInterface &) = delete; + ProcessorInterface &operator=(const ProcessorInterface &) = delete; + + virtual void setUnsavedFiles(const V2::FileContainers &unsavedFiles) = 0; + virtual bool isUsed() const = 0; + virtual void setIsUsed(bool isUsed) = 0; + virtual void clear() = 0; + virtual void doInMainThreadAfterFinished() = 0; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolscollectormanager.h b/src/tools/clangpchmanagerbackend/source/processormanager.h index d5a020904f..be20c5d87f 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollectormanager.h +++ b/src/tools/clangpchmanagerbackend/source/processormanager.h @@ -25,8 +25,8 @@ #pragma once -#include "symbolscollectormanagerinterface.h" -#include "symbolscollectorinterface.h" + +#include "processormanagerinterface.h" #include "generatedfiles.h" #include <memory> @@ -38,51 +38,54 @@ class Database; namespace ClangBackEnd { class GeneratedFiles; -class SymbolsCollector; -template<typename SymbolsCollector> -class SymbolsCollectorManager final : public SymbolsCollectorManagerInterface + +template <typename ProcessorType> +class ProcessorManager : public ProcessorManagerInterface { public: - SymbolsCollectorManager(Sqlite::Database &database, - const GeneratedFiles &generatedFiles) - : m_database(database), - m_generatedFiles(generatedFiles) + using Processor = ProcessorType; + ProcessorManager(const GeneratedFiles &generatedFiles) + : m_generatedFiles(generatedFiles) {} - SymbolsCollector &unusedSymbolsCollector() override + Processor &unusedProcessor() override { - auto split = std::partition(m_collectors.begin(), - m_collectors.end(), + auto split = std::partition(m_processors.begin(), + m_processors.end(), [] (const auto &collector) { return collector->isUsed(); }); - auto freeCollectors = std::distance(split, m_collectors.end()); + auto freeCollectors = std::distance(split, m_processors.end()); if (freeCollectors > 0) return initializedCollector(*split->get()); - m_collectors.emplace_back(std::make_unique<SymbolsCollector>(m_database)); + m_processors.push_back(createProcessor()); - return initializedCollector(*m_collectors.back().get()); + return initializedCollector(*m_processors.back().get()); } - const std::vector<std::unique_ptr<SymbolsCollector>> &collectors() const + const std::vector<std::unique_ptr<Processor>> &processors() const { - return m_collectors; + return m_processors; } +protected: + ~ProcessorManager() = default; + virtual std::unique_ptr<Processor> createProcessor() const = 0; + private: - SymbolsCollector &initializedCollector(SymbolsCollector &collector) + Processor &initializedCollector(Processor &creator) { - collector.setIsUsed(true); - collector.setUnsavedFiles(m_generatedFiles.fileContainers()); - return collector; + creator.setIsUsed(true); + creator.setUnsavedFiles(m_generatedFiles.fileContainers()); + return creator; } + private: - std::vector<std::unique_ptr<SymbolsCollector>> m_collectors; - Sqlite::Database &m_database; + std::vector<std::unique_ptr<Processor>> m_processors; const GeneratedFiles &m_generatedFiles; }; diff --git a/src/tools/clangrefactoringbackend/source/symbolscollectormanagerinterface.h b/src/tools/clangpchmanagerbackend/source/processormanagerinterface.h index b0cb3a0332..13d02fbc94 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollectormanagerinterface.h +++ b/src/tools/clangpchmanagerbackend/source/processormanagerinterface.h @@ -25,25 +25,23 @@ #pragma once -#include <filecontainerv2.h> +#include <processorinterface.h> -#include <vector> +#include <filecontainerv2.h> namespace ClangBackEnd { -class SymbolsCollectorInterface; - -class SymbolsCollectorManagerInterface +class ProcessorManagerInterface { public: - SymbolsCollectorManagerInterface() = default; - SymbolsCollectorManagerInterface(const SymbolsCollectorManagerInterface &) = delete; - SymbolsCollectorManagerInterface &operator=(const SymbolsCollectorManagerInterface &) = delete; + ProcessorManagerInterface() = default; + ProcessorManagerInterface(const ProcessorManagerInterface &) = delete; + ProcessorManagerInterface &operator=(const ProcessorManagerInterface &) = delete; - virtual SymbolsCollectorInterface &unusedSymbolsCollector() = 0; + virtual ProcessorInterface &unusedProcessor() = 0; protected: - ~SymbolsCollectorManagerInterface() = default; + ~ProcessorManagerInterface() = default; }; } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/projectpartqueue.cpp b/src/tools/clangpchmanagerbackend/source/projectpartqueue.cpp new file mode 100644 index 0000000000..e61913ac04 --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/projectpartqueue.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "projectpartqueue.h" + +#include <pchcreatorinterface.h> +#include <precompiledheaderstorageinterface.h> +#include <sqlitetransaction.h> + +namespace ClangBackEnd { + +void ProjectPartQueue::addProjectParts(V2::ProjectPartContainers &&projectParts) +{ + auto compare = [](const V2::ProjectPartContainer &first, const V2::ProjectPartContainer &second) { + return first.projectPartId < second.projectPartId; + }; + + V2::ProjectPartContainers mergedProjectParts; + mergedProjectParts.reserve(m_projectParts.size() + projectParts.size()); + std::set_union(std::make_move_iterator(projectParts.begin()), + std::make_move_iterator(projectParts.end()), + std::make_move_iterator(m_projectParts.begin()), + std::make_move_iterator(m_projectParts.end()), + std::back_inserter(mergedProjectParts), + compare); + + m_projectParts = std::move(mergedProjectParts); +} + +class CompareDifference +{ +public: + bool operator()(const V2::ProjectPartContainer &first, const Utils::SmallString &second) + { + return first.projectPartId < second; + } + + bool operator()(const Utils::SmallString &first, const V2::ProjectPartContainer &second) + { + return first < second.projectPartId; + } +}; + +void ProjectPartQueue::removeProjectParts(const Utils::SmallStringVector &projectsPartIds) +{ + V2::ProjectPartContainers notToBeRemovedProjectParts; + notToBeRemovedProjectParts.reserve(m_projectParts.size()); + std::set_difference(std::make_move_iterator(m_projectParts.begin()), + std::make_move_iterator(m_projectParts.end()), + projectsPartIds.begin(), + projectsPartIds.end(), + std::back_inserter(notToBeRemovedProjectParts), + CompareDifference{}); + + m_projectParts = std::move(notToBeRemovedProjectParts); +} + +void ProjectPartQueue::processEntries() +{ + uint taskCount = m_taskScheduler.freeSlots(); + + auto newEnd = std::prev(m_projectParts.end(), std::min<int>(int(taskCount), int(m_projectParts.size()))); + m_taskScheduler.addTasks( + createPchTasks({std::make_move_iterator(newEnd), + std::make_move_iterator(m_projectParts.end())})); + m_projectParts.erase(newEnd, m_projectParts.end()); +} + +const V2::ProjectPartContainers &ProjectPartQueue::projectParts() const +{ + return m_projectParts; +} + +std::vector<ProjectPartQueue::Task> ProjectPartQueue::createPchTasks( + V2::ProjectPartContainers &&projectParts) const +{ + std::vector<Task> tasks; + tasks.reserve(projectParts.size()); + + auto convert = [this] (auto &&projectPart) { + return [projectPart=std::move(projectPart), this] (PchCreatorInterface &pchCreator) { + pchCreator.generatePch(projectPart); + const auto &projectPartPch = pchCreator.projectPartPch(); + Sqlite::ImmediateTransaction transaction(m_transactionsInterface); + if (projectPartPch.pchPath.empty()) { + m_precompiledHeaderStorage.deletePrecompiledHeader(projectPartPch.projectPartId); + } else { + m_precompiledHeaderStorage.insertPrecompiledHeader(projectPartPch.projectPartId, + projectPartPch.pchPath, + projectPartPch.lastModified); + } + transaction.commit(); + }; + }; + + std::transform(std::make_move_iterator(projectParts.begin()), + std::make_move_iterator(projectParts.end()), + std::back_inserter(tasks), + convert); + + return tasks; +} + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskschedulerinterface.h b/src/tools/clangpchmanagerbackend/source/projectpartqueue.h index c71454df3d..55b490fc64 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexertaskschedulerinterface.h +++ b/src/tools/clangpchmanagerbackend/source/projectpartqueue.h @@ -25,8 +25,8 @@ #pragma once -#include <functional> -#include <vector> +#include "projectpartqueueinterface.h" +#include "taskschedulerinterface.h" namespace Sqlite { class TransactionInterface; @@ -34,27 +34,37 @@ class TransactionInterface; namespace ClangBackEnd { -class SymbolsCollectorInterface; -class SymbolStorageInterface; +class PrecompiledHeaderStorageInterface; +class PchTaskSchedulerInterface; +class PchCreatorInterface; -using uint = unsigned int; - -class SymbolIndexerTaskSchedulerInterface +class ProjectPartQueue final : public ProjectPartQueueInterface { public: - using Task = std::function<void(SymbolsCollectorInterface &symbolsCollector, - SymbolStorageInterface &symbolStorage, - Sqlite::TransactionInterface &transaction)>; + using Task = std::function<void (PchCreatorInterface&)>; + + ProjectPartQueue(TaskSchedulerInterface<Task> &taskScheduler, + PrecompiledHeaderStorageInterface &precompiledHeaderStorage, + Sqlite::TransactionInterface &transactionsInterface) + : m_taskScheduler(taskScheduler), + m_precompiledHeaderStorage(precompiledHeaderStorage), + m_transactionsInterface(transactionsInterface) + {} + + void addProjectParts(V2::ProjectPartContainers &&projectParts); + void removeProjectParts(const Utils::SmallStringVector &projectsPartIds); + + void processEntries(); - SymbolIndexerTaskSchedulerInterface() = default; - SymbolIndexerTaskSchedulerInterface(const SymbolIndexerTaskSchedulerInterface &) = delete; - SymbolIndexerTaskSchedulerInterface &operator=(const SymbolIndexerTaskSchedulerInterface &) = delete; + const V2::ProjectPartContainers &projectParts() const; - virtual void addTasks(std::vector<Task> &&tasks) = 0; - virtual uint freeSlots() = 0; + std::vector<Task> createPchTasks(V2::ProjectPartContainers &&projectParts) const; -protected: - ~SymbolIndexerTaskSchedulerInterface() = default; +private: + V2::ProjectPartContainers m_projectParts; + TaskSchedulerInterface<Task> &m_taskScheduler; + PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage; + Sqlite::TransactionInterface &m_transactionsInterface; }; } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/projectpartqueueinterface.h b/src/tools/clangpchmanagerbackend/source/projectpartqueueinterface.h new file mode 100644 index 0000000000..0b705fe312 --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/projectpartqueueinterface.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "queueinterface.h" + +#include <projectpartcontainerv2.h> + +namespace ClangBackEnd { + +class ProjectPartQueueInterface : public QueueInterface +{ +public: + virtual void addProjectParts(V2::ProjectPartContainers &&projectParts) = 0; + virtual void removeProjectParts(const Utils::SmallStringVector &projectsPartIds) = 0; + +protected: + ~ProjectPartQueueInterface() = default; +}; +} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/projectparts.cpp b/src/tools/clangpchmanagerbackend/source/projectparts.cpp index b1689f036d..6be06380bf 100644 --- a/src/tools/clangpchmanagerbackend/source/projectparts.cpp +++ b/src/tools/clangpchmanagerbackend/source/projectparts.cpp @@ -35,9 +35,7 @@ inline namespace Pch { V2::ProjectPartContainers ProjectParts::update(V2::ProjectPartContainers &&projectsParts) { - auto uniqueProjectParts = ProjectParts::uniqueProjectParts(std::move(projectsParts)); - - auto updatedProjectPartContainers = newProjectParts(std::move(uniqueProjectParts)); + auto updatedProjectPartContainers = newProjectParts(std::move(projectsParts)); mergeProjectParts(updatedProjectPartContainers); @@ -68,16 +66,6 @@ V2::ProjectPartContainers ProjectParts::projects(const Utils::SmallStringVector return projectPartsWithIds; } -V2::ProjectPartContainers ProjectParts::uniqueProjectParts(V2::ProjectPartContainers &&projectsParts) -{ - std::sort(projectsParts.begin(), projectsParts.end()); - auto newEnd = std::unique(projectsParts.begin(), projectsParts.end()); - - projectsParts.erase(newEnd, projectsParts.end()); - - return std::move(projectsParts); -} - V2::ProjectPartContainers ProjectParts::newProjectParts(V2::ProjectPartContainers &&projectsParts) const { V2::ProjectPartContainers updatedProjectPartContainers; diff --git a/src/tools/clangpchmanagerbackend/source/projectparts.h b/src/tools/clangpchmanagerbackend/source/projectparts.h index 67c8bc0256..c0d9c61e7f 100644 --- a/src/tools/clangpchmanagerbackend/source/projectparts.h +++ b/src/tools/clangpchmanagerbackend/source/projectparts.h @@ -43,7 +43,6 @@ public: V2::ProjectPartContainers projects(const Utils::SmallStringVector &projectPartIds) const override; unittest_public: - static V2::ProjectPartContainers uniqueProjectParts(V2::ProjectPartContainers &&projectsParts); V2::ProjectPartContainers newProjectParts(V2::ProjectPartContainers &&projectsParts) const; void mergeProjectParts(const V2::ProjectPartContainers &projectsParts); const V2::ProjectPartContainers &projectParts() const; diff --git a/src/tools/clangpchmanagerbackend/source/pchgeneratorinterface.h b/src/tools/clangpchmanagerbackend/source/queueinterface.h index c25eb248b2..d8ec0c69ed 100644 --- a/src/tools/clangpchmanagerbackend/source/pchgeneratorinterface.h +++ b/src/tools/clangpchmanagerbackend/source/queueinterface.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -29,21 +29,16 @@ namespace ClangBackEnd { -class ProjectPartPch; - -class PchGeneratorInterface +class QueueInterface { public: - PchGeneratorInterface() = default; - PchGeneratorInterface(const PchGeneratorInterface &) = delete; - PchGeneratorInterface &operator=(const PchGeneratorInterface &) = delete; + QueueInterface() = default; + QueueInterface(const QueueInterface &) = delete; + QueueInterface &operator=(const QueueInterface &) = delete; - virtual void startTask(Utils::SmallStringVector &&compilerArguments, - ProjectPartPch &&projectPartPch) = 0; + virtual void processEntries() = 0; protected: - ~PchGeneratorInterface() = default; + ~QueueInterface() = default; }; - } // namespace ClangBackEnd - diff --git a/src/tools/clangpchmanagerbackend/source/taskscheduler.h b/src/tools/clangpchmanagerbackend/source/taskscheduler.h new file mode 100644 index 0000000000..35c3c51984 --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/taskscheduler.h @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "taskschedulerinterface.h" +#include "symbolindexertask.h" +#include "queueinterface.h" + +#include <processormanagerinterface.h> +#include <symbolindexertaskqueueinterface.h> +#include <symbolscollectorinterface.h> + +#include <QAbstractEventDispatcher> +#include <QCoreApplication> +#include <QMetaObject> +#include <QThread> + +#include <algorithm> +#include <functional> +#include <future> +#include <thread> +#include <vector> + +namespace Sqlite { +class TransactionInterface; +}; + +namespace ClangBackEnd { + +class FilePathCachingInterface; +class ProcessorManagerInterface; +class QueueInterface; +class SymbolStorageInterface; + +template <typename ProcessorManager, + typename Task> +class TaskScheduler : public TaskSchedulerInterface<Task> +{ +public: + using ProcessorInterface = typename ProcessorManager::Processor; + using Future = std::future<ProcessorInterface&>; + + TaskScheduler(ProcessorManager &symbolsCollectorManager, + QueueInterface &queue, + uint hardwareConcurrency, + std::launch launchPolicy = std::launch::async) + : m_processorManager(symbolsCollectorManager), + m_queue(queue), + m_hardwareConcurrency(hardwareConcurrency), + m_launchPolicy(launchPolicy) + {} + + void addTasks(std::vector<Task> &&tasks) + { + for (auto &task : tasks) { + auto callWrapper = [&, task=std::move(task)] (auto processor) + -> ProcessorInterface& { + task(processor.get()); + executeInLoop([&] { + m_queue.processEntries(); + }); + + return processor; + }; + m_futures.emplace_back(std::async(m_launchPolicy, + std::move(callWrapper), + std::ref(m_processorManager.unusedProcessor()))); + } + } + + const std::vector<Future> &futures() const + { + return m_futures; + } + + uint freeSlots() + { + removeFinishedFutures(); + + if (m_isDisabled) + return 0; + + return uint(std::max(int(m_hardwareConcurrency) - int(m_futures.size()), 0)); + } + + void syncTasks() + { + for (auto &future : m_futures) + future.wait(); + } + + void disable() + { + m_isDisabled = true; + } + +private: + void removeFinishedFutures() + { + auto notReady = [] (Future &future) { + return future.wait_for(std::chrono::duration<int>::zero()) != std::future_status::ready; + }; + + auto split = std::partition(m_futures.begin(), m_futures.end(), notReady); + + std::for_each(split, m_futures.end(), [] (Future &future) { + ProcessorInterface &processor = future.get(); + processor.doInMainThreadAfterFinished(); + processor.setIsUsed(false); + processor.clear(); + }); + + m_futures.erase(split, m_futures.end()); + } + + #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) + template <typename CallableType> + class CallableEvent : public QEvent { + public: + using Callable = std::decay_t<CallableType>; + CallableEvent(Callable &&callable) + : QEvent(QEvent::None), + callable(std::move(callable)) + {} + CallableEvent(const Callable &callable) + : QEvent(QEvent::None), + callable(callable) + {} + + ~CallableEvent() + { + callable(); + } + public: + Callable callable; + }; + + template <typename Callable> + void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance()) { + if (QThread *thread = qobject_cast<QThread*>(object)) + object = QAbstractEventDispatcher::instance(thread); + + QCoreApplication::postEvent(object, + new CallableEvent<Callable>(std::forward<Callable>(callable)), + Qt::HighEventPriority); + } + #else + template <typename Callable> + void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance()) { + if (QThread *thread = qobject_cast<QThread*>(object)) + object = QAbstractEventDispatcher::instance(thread); + + QMetaObject::invokeMethod(object, std::forward<Callable>(callable)); + } + #endif + +private: + std::vector<Future> m_futures; + ProcessorManager &m_processorManager; + QueueInterface &m_queue; + uint m_hardwareConcurrency; + std::launch m_launchPolicy; + bool m_isDisabled = false; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/pchgeneratornotifierinterface.h b/src/tools/clangpchmanagerbackend/source/taskschedulerinterface.h index 32f47c9f5c..a79a3ed8d2 100644 --- a/src/tools/clangpchmanagerbackend/source/pchgeneratornotifierinterface.h +++ b/src/tools/clangpchmanagerbackend/source/taskschedulerinterface.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,29 +25,25 @@ #pragma once -#include <iosfwd> +#include <vector> namespace ClangBackEnd { -class ProjectPartPch; +using uint = unsigned int; -enum class TaskFinishStatus -{ - Successfully, - Unsuccessfully -}; - -class PchGeneratorNotifierInterface +template <typename Task> +class TaskSchedulerInterface { public: - PchGeneratorNotifierInterface() = default; - PchGeneratorNotifierInterface(const PchGeneratorNotifierInterface &) = delete; - PchGeneratorNotifierInterface &operator=(const PchGeneratorNotifierInterface &) = delete; + TaskSchedulerInterface() = default; + TaskSchedulerInterface(const TaskSchedulerInterface &) = delete; + TaskSchedulerInterface &operator=(const TaskSchedulerInterface &) = delete; - virtual void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) = 0; + virtual void addTasks(std::vector<Task> &&tasks) = 0; + virtual uint freeSlots() = 0; protected: - ~PchGeneratorNotifierInterface() = default; + ~TaskSchedulerInterface() = default; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/clangrefactoringbackend.pro b/src/tools/clangrefactoringbackend/clangrefactoringbackend.pro index 072d254728..ea66a43b61 100644 --- a/src/tools/clangrefactoringbackend/clangrefactoringbackend.pro +++ b/src/tools/clangrefactoringbackend/clangrefactoringbackend.pro @@ -17,6 +17,7 @@ QT -= gui LIBS += $$LIBTOOLING_LIBS INCLUDEPATH += $$LLVM_INCLUDEPATH +INCLUDEPATH += ../clangpchmanagerbackend/source QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri index d15e0f625d..26fa44aa68 100644 --- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri +++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri @@ -24,11 +24,7 @@ HEADERS += \ $$PWD/indexdataconsumer.h \ $$PWD/sourcesmanager.h \ $$PWD/symbolindexertaskqueue.h \ - $$PWD/symbolindexertaskscheduler.h \ - $$PWD/symbolscollectormanagerinterface.h \ $$PWD/symbolindexertaskqueueinterface.h \ - $$PWD/symbolindexertaskschedulerinterface.h \ - $$PWD/symbolscollectormanager.h \ $$PWD/symbolindexertask.h !isEmpty(LIBTOOLING_LIBS) { @@ -74,6 +70,4 @@ SOURCES += \ $$PWD/sourcerangefilter.cpp \ $$PWD/symbolindexer.cpp \ $$PWD/projectpartartefact.cpp \ - $$PWD/filestatuscache.cpp \ - $$PWD/symbolindexertaskqueue.cpp \ - $$PWD/symbolindexertaskscheduler.cpp + $$PWD/filestatuscache.cpp diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp index 5c9f0cbccc..272e89fa89 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp @@ -101,27 +101,25 @@ void SymbolIndexer::updateProjectPart(V2::ProjectPartContainer &&projectPart) std::vector<SymbolIndexerTask> symbolIndexerTask; symbolIndexerTask.reserve(projectPart.sourcePathIds.size()); for (FilePathId sourcePathId : projectPart.sourcePathIds) { - auto indexing = [projectPartId, arguments, sourcePathId] - (SymbolsCollectorInterface &symbolsCollector, - SymbolStorageInterface &symbolStorage, - Sqlite::TransactionInterface &transactionInterface) { + auto indexing = [projectPartId, arguments, sourcePathId, this] + (SymbolsCollectorInterface &symbolsCollector) { symbolsCollector.setFile(sourcePathId, arguments); symbolsCollector.collectSymbols(); - Sqlite::ImmediateTransaction transaction{transactionInterface}; + Sqlite::ImmediateTransaction transaction{m_transactionInterface}; - symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), - symbolsCollector.sourceLocations()); + m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), + symbolsCollector.sourceLocations()); - symbolStorage.updateProjectPartSources(projectPartId, - symbolsCollector.sourceFiles()); + m_symbolStorage.updateProjectPartSources(projectPartId, + symbolsCollector.sourceFiles()); - symbolStorage.insertOrUpdateUsedMacros(symbolsCollector.usedMacros()); + m_symbolStorage.insertOrUpdateUsedMacros(symbolsCollector.usedMacros()); - symbolStorage.insertFileStatuses(symbolsCollector.fileStatuses()); + m_symbolStorage.insertFileStatuses(symbolsCollector.fileStatuses()); - symbolStorage.insertOrUpdateSourceDependencies(symbolsCollector.sourceDependencies()); + m_symbolStorage.insertOrUpdateSourceDependencies(symbolsCollector.sourceDependencies()); transaction.commit(); }; @@ -130,7 +128,7 @@ void SymbolIndexer::updateProjectPart(V2::ProjectPartContainer &&projectPart) } m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask)); - m_symbolIndexerTaskQueue.processTasks(); + m_symbolIndexerTaskQueue.processEntries(); } void SymbolIndexer::pathsWithIdsChanged(const Utils::SmallStringVector &) @@ -146,7 +144,7 @@ void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds) updateChangedPath(filePathId, symbolIndexerTask); m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask)); - m_symbolIndexerTaskQueue.processTasks(); + m_symbolIndexerTaskQueue.processEntries(); } void SymbolIndexer::updateChangedPath(FilePathId filePathId, @@ -169,26 +167,24 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId, const Utils::SmallStringVector arguments = compilerArguments(artefact.compilerArguments, optionalProjectPartPch); - auto indexing = [projectPartId=artefact.projectPartId, arguments, filePathId] - (SymbolsCollectorInterface &symbolsCollector, - SymbolStorageInterface &symbolStorage, - Sqlite::TransactionInterface &transactionInterface) { + auto indexing = [projectPartId=artefact.projectPartId, arguments, filePathId, this] + (SymbolsCollectorInterface &symbolsCollector) { symbolsCollector.setFile(filePathId, arguments); symbolsCollector.collectSymbols(); - Sqlite::ImmediateTransaction transaction{transactionInterface}; + Sqlite::ImmediateTransaction transaction{m_transactionInterface}; - symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), - symbolsCollector.sourceLocations()); + m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), + symbolsCollector.sourceLocations()); - symbolStorage.updateProjectPartSources(projectPartId, symbolsCollector.sourceFiles()); + m_symbolStorage.updateProjectPartSources(projectPartId, symbolsCollector.sourceFiles()); - symbolStorage.insertOrUpdateUsedMacros(symbolsCollector.usedMacros()); + m_symbolStorage.insertOrUpdateUsedMacros(symbolsCollector.usedMacros()); - symbolStorage.insertFileStatuses(symbolsCollector.fileStatuses()); + m_symbolStorage.insertFileStatuses(symbolsCollector.fileStatuses()); - symbolStorage.insertOrUpdateSourceDependencies(symbolsCollector.sourceDependencies()); + m_symbolStorage.insertOrUpdateSourceDependencies(symbolsCollector.sourceDependencies()); transaction.commit(); }; diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertask.h b/src/tools/clangrefactoringbackend/source/symbolindexertask.h index 3b18681e07..de3303815d 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexertask.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexertask.h @@ -35,16 +35,13 @@ class TransactionInterface; namespace ClangBackEnd { -class SymbolIndexerTaskSchedulerInterface; class SymbolsCollectorInterface; class SymbolStorageInterface; class SymbolIndexerTask { public: - using Callable = std::function<void(SymbolsCollectorInterface &symbolsCollector, - SymbolStorageInterface &symbolStorage, - Sqlite::TransactionInterface &transaction)>; + using Callable = std::function<void(SymbolsCollectorInterface &symbolsCollector)>; SymbolIndexerTask(FilePathId filePathId, int projectPartId, diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.cpp b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.cpp deleted file mode 100644 index bb891467a6..0000000000 --- a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "symbolindexertaskqueue.h" - -#include <symbolindexertaskschedulerinterface.h> - -#include <utils/algorithm.h> - -namespace ClangBackEnd { - -void SymbolIndexerTaskQueue::addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks) -{ - auto merge = [] (SymbolIndexerTask &&first, SymbolIndexerTask &&second) { - first.callable = std::move(second.callable); - - return std::move(first); - }; - - m_tasks = Utils::setUnionMerge<std::vector<SymbolIndexerTask>>(tasks, m_tasks, merge); -} - -void SymbolIndexerTaskQueue::removeTasks(const std::vector<int> &projectPartIds) -{ - auto shouldBeRemoved = [&] (const SymbolIndexerTask& task) { - return std::binary_search(projectPartIds.begin(), projectPartIds.end(), task.projectPartId); - }; - - auto newEnd = std::remove_if(m_tasks.begin(), m_tasks.end(), shouldBeRemoved); - - m_tasks.erase(newEnd, m_tasks.end()); -} - -const std::vector<SymbolIndexerTask> &SymbolIndexerTaskQueue::tasks() const -{ - return m_tasks; -} - -void SymbolIndexerTaskQueue::processTasks() -{ - int taskCount = m_symbolIndexerScheduler.freeSlots(); - - auto newEnd = std::prev(m_tasks.end(), std::min<int>(taskCount, int(m_tasks.size()))); - m_symbolIndexerScheduler.addTasks({std::make_move_iterator(newEnd), - std::make_move_iterator(m_tasks.end())}); - m_tasks.erase(newEnd, m_tasks.end()); -} - -} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h index 6a627e8865..3dc54998d0 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h @@ -29,7 +29,9 @@ #include "symbolindexertask.h" #include <filepathid.h> +#include <taskschedulerinterface.h> +#include <utils/algorithm.h> #include <utils/smallstringvector.h> #include <functional> @@ -41,29 +43,59 @@ class TransactionInterface; namespace ClangBackEnd { -class SymbolIndexerTaskSchedulerInterface; class SymbolsCollectorInterface; class SymbolStorageInterface; class SymbolIndexerTaskQueue final : public SymbolIndexerTaskQueueInterface { public: - SymbolIndexerTaskQueue(SymbolIndexerTaskSchedulerInterface &symbolIndexerTaskScheduler) + using Task = SymbolIndexerTask::Callable; + + SymbolIndexerTaskQueue(TaskSchedulerInterface<Task> &symbolIndexerTaskScheduler) : m_symbolIndexerScheduler(symbolIndexerTaskScheduler) {} - void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks); - void removeTasks(const std::vector<int> &projectPartIds); + void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks) + { + auto merge = [] (SymbolIndexerTask &&first, SymbolIndexerTask &&second) { + first.callable = std::move(second.callable); + + return std::move(first); + }; + + m_tasks = Utils::setUnionMerge<std::vector<SymbolIndexerTask>>(tasks, m_tasks, merge); + } + void removeTasks(const std::vector<int> &projectPartIds) + { + auto shouldBeRemoved = [&] (const SymbolIndexerTask& task) { + return std::binary_search(projectPartIds.begin(), projectPartIds.end(), task.projectPartId); + }; + + auto newEnd = std::remove_if(m_tasks.begin(), m_tasks.end(), shouldBeRemoved); + + m_tasks.erase(newEnd, m_tasks.end()); + } + + const std::vector<SymbolIndexerTask> &tasks() const + { + return m_tasks; + } - const std::vector<SymbolIndexerTask> &tasks() const; + void processEntries() + { + uint taskCount = m_symbolIndexerScheduler.freeSlots(); - void processTasks(); + auto newEnd = std::prev(m_tasks.end(), std::min<int>(int(taskCount), int(m_tasks.size()))); + m_symbolIndexerScheduler.addTasks({std::make_move_iterator(newEnd), + std::make_move_iterator(m_tasks.end())}); + m_tasks.erase(newEnd, m_tasks.end()); + } void syncTasks(); private: std::vector<Utils::SmallString> m_projectPartIds; std::vector<SymbolIndexerTask> m_tasks; - SymbolIndexerTaskSchedulerInterface &m_symbolIndexerScheduler; + TaskSchedulerInterface<Task> &m_symbolIndexerScheduler; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueueinterface.h b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueueinterface.h index 9e96a79e6c..dfcc78bd23 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueueinterface.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueueinterface.h @@ -25,24 +25,21 @@ #pragma once +#include <queueinterface.h> + #include <utils/smallstringvector.h> namespace ClangBackEnd { class SymbolIndexerTask; -class SymbolIndexerTaskQueueInterface +class SymbolIndexerTaskQueueInterface : public QueueInterface { public: - SymbolIndexerTaskQueueInterface() = default; - SymbolIndexerTaskQueueInterface(const SymbolIndexerTaskQueueInterface &) = delete; - SymbolIndexerTaskQueueInterface &operator=(const SymbolIndexerTaskQueueInterface &) = delete; - virtual void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks) = 0 /* [[expects: std::is_sorted(tasks)]] */; virtual void removeTasks(const std::vector<int> &projectPartIds) = 0 /* [[expects: std::is_sorted(projectPartIds)]] */; - virtual void processTasks() = 0; protected: ~SymbolIndexerTaskQueueInterface() = default; diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.cpp b/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.cpp deleted file mode 100644 index e9f5cbe285..0000000000 --- a/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "symbolindexertaskscheduler.h" - -#include <symbolindexertaskqueueinterface.h> -#include <symbolscollectormanagerinterface.h> -#include <symbolscollectorinterface.h> - -#include <QAbstractEventDispatcher> -#include <QCoreApplication> -#include <QMetaObject> -#include <QThread> - -#include <algorithm> -#include <thread> - -namespace ClangBackEnd { -namespace { -#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) -template <typename CallableType> -class CallableEvent : public QEvent { -public: - using Callable = std::decay_t<CallableType>; - CallableEvent(Callable &&callable) - : QEvent(QEvent::None), - callable(std::move(callable)) - {} - CallableEvent(const Callable &callable) - : QEvent(QEvent::None), - callable(callable) - {} - - ~CallableEvent() - { - callable(); - } -public: - Callable callable; -}; - -template <typename Callable> -void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance()) { - if (QThread *thread = qobject_cast<QThread*>(object)) - object = QAbstractEventDispatcher::instance(thread); - - QCoreApplication::postEvent(object, - new CallableEvent<Callable>(std::forward<Callable>(callable)), - Qt::HighEventPriority); -} -#else -template <typename Callable> -void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance()) { - if (QThread *thread = qobject_cast<QThread*>(object)) - object = QAbstractEventDispatcher::instance(thread); - - QMetaObject::invokeMethod(object, std::forward<Callable>(callable)); -} -#endif -} - -void SymbolIndexerTaskScheduler::addTasks(std::vector<Task> &&tasks) -{ - for (auto &task : tasks) { - auto callWrapper = [&, task=std::move(task)] ( - std::reference_wrapper<SymbolsCollectorInterface> symbolsCollector) - -> SymbolsCollectorInterface& { - task(symbolsCollector.get(), m_symbolStorage, m_transactionInterface); - executeInLoop([&] { - m_symbolIndexerTaskQueue.processTasks(); - }); - - return symbolsCollector; - }; - m_futures.emplace_back(std::async(m_launchPolicy, - std::move(callWrapper), - std::ref(m_symbolsCollectorManager.unusedSymbolsCollector()))); - } -} - -const std::vector<SymbolIndexerTaskScheduler::Future> &SymbolIndexerTaskScheduler::futures() const -{ - return m_futures; -} - -uint SymbolIndexerTaskScheduler::freeSlots() -{ - removeFinishedFutures(); - - if (m_isDisabled) - return 0; - - return uint(std::max(int(m_hardware_concurrency) - int(m_futures.size()), 0)); -} - -void SymbolIndexerTaskScheduler::syncTasks() -{ - for (auto &future : m_futures) - future.wait(); -} - -void SymbolIndexerTaskScheduler::disable() -{ - m_isDisabled = true; -} - -void SymbolIndexerTaskScheduler::removeFinishedFutures() -{ - auto notReady = [] (Future &future) { - return future.wait_for(std::chrono::duration<int>::zero()) != std::future_status::ready; - }; - - auto split = std::partition(m_futures.begin(), m_futures.end(), notReady); - - std::for_each(split, m_futures.end(), [] (Future &future) { - SymbolsCollectorInterface &symbolCollector = future.get(); - symbolCollector.setIsUsed(false); - symbolCollector.clear(); - }); - - m_futures.erase(split, m_futures.end()); -} - -} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.h b/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.h deleted file mode 100644 index 6182376dab..0000000000 --- a/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "symbolindexertaskschedulerinterface.h" -#include "symbolindexertask.h" - -#include <functional> -#include <future> -#include <vector> - -namespace Sqlite { -class TransactionInterface; -}; - -namespace ClangBackEnd { - -class FilePathCachingInterface; -class SymbolsCollectorInterface; -class SymbolsCollectorManagerInterface; -class SymbolIndexerTaskQueueInterface; -class SymbolStorageInterface; - -class SymbolIndexerTaskScheduler final : public SymbolIndexerTaskSchedulerInterface -{ -public: - using Task = SymbolIndexerTask::Callable; - using Future = std::future<SymbolsCollectorInterface&>; - - SymbolIndexerTaskScheduler(SymbolsCollectorManagerInterface &symbolsCollectorManager, - SymbolStorageInterface &symbolStorage, - Sqlite::TransactionInterface &transactionInterface, - SymbolIndexerTaskQueueInterface &symbolIndexerTaskQueue, - uint hardware_concurrency, - std::launch launchPolicy = std::launch::async) - : m_symbolsCollectorManager(symbolsCollectorManager), - m_symbolStorage(symbolStorage), - m_transactionInterface(transactionInterface), - m_symbolIndexerTaskQueue(symbolIndexerTaskQueue), - m_hardware_concurrency(hardware_concurrency), - m_launchPolicy(launchPolicy) - {} - - void addTasks(std::vector<Task> &&tasks); - - const std::vector<Future> &futures() const; - - uint freeSlots(); - - void syncTasks(); - - void disable(); - -private: - void removeFinishedFutures(); - -private: - std::vector<Future> m_futures; - SymbolsCollectorManagerInterface &m_symbolsCollectorManager; - SymbolStorageInterface &m_symbolStorage; - Sqlite::TransactionInterface &m_transactionInterface; - SymbolIndexerTaskQueueInterface &m_symbolIndexerTaskQueue; - uint m_hardware_concurrency; - std::launch m_launchPolicy; - bool m_isDisabled = false; -}; - -} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.h b/src/tools/clangrefactoringbackend/source/symbolindexing.h index 8f7821bddb..918edb626a 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexing.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexing.h @@ -30,9 +30,9 @@ #include "storagesqlitestatementfactory.h" #include "symbolindexer.h" #include "symbolscollector.h" -#include "symbolscollectormanager.h" +#include "processormanager.h" #include "symbolindexertaskqueue.h" -#include "symbolindexertaskscheduler.h" +#include "taskscheduler.h" #include "symbolstorage.h" #include <refactoringdatabaseinitializer.h> @@ -48,19 +48,40 @@ namespace ClangBackEnd { +class SymbolsCollectorManager; + +class SymbolsCollectorManager final : public ClangBackEnd::ProcessorManager<SymbolsCollector> +{ +public: + using Processor = SymbolsCollector; + SymbolsCollectorManager(const ClangBackEnd::GeneratedFiles &generatedFiles, + Sqlite::Database &database) + : ProcessorManager(generatedFiles), + m_database(database) + {} + +protected: + std::unique_ptr<SymbolsCollector> createProcessor() const + { + return std::make_unique<SymbolsCollector>(m_database); + } + +private: + Sqlite::Database &m_database; +}; + class SymbolIndexing final : public SymbolIndexingInterface { public: using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<Sqlite::Database>; using Storage = ClangBackEnd::SymbolStorage<StatementFactory>; - SymbolIndexing(Sqlite::Database &database, FilePathCachingInterface &filePathCache, const GeneratedFiles &generatedFiles) : m_filePathCache(filePathCache), m_statementFactory(database), - m_collectorManger(database, generatedFiles), - m_indexerScheduler(m_collectorManger, m_symbolStorage, database, m_indexerQueue, std::thread::hardware_concurrency()) + m_collectorManger(generatedFiles, database), + m_indexerScheduler(m_collectorManger, m_indexerQueue, std::thread::hardware_concurrency()) { } @@ -86,12 +107,13 @@ public: void updateProjectParts(V2::ProjectPartContainers &&projectParts) override; private: + using SymbolIndexerTaskScheduler = TaskScheduler<SymbolsCollectorManager, SymbolIndexerTask::Callable>; FilePathCachingInterface &m_filePathCache; StatementFactory m_statementFactory; Storage m_symbolStorage{m_statementFactory}; ClangPathWatcher<QFileSystemWatcher, QTimer> m_sourceWatcher{m_filePathCache}; FileStatusCache m_fileStatusCache{m_filePathCache}; - SymbolsCollectorManager<SymbolsCollector> m_collectorManger; + SymbolsCollectorManager m_collectorManger; SymbolIndexerTaskScheduler m_indexerScheduler; SymbolIndexerTaskQueue m_indexerQueue{m_indexerScheduler}; SymbolIndexer m_indexer{m_indexerQueue, diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp index 53e0bbba6e..afa01de2e9 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp @@ -129,6 +129,10 @@ void SymbolsCollector::collectSymbols() &m_collectMacrosSourceFileCallbacks).get()); } +void SymbolsCollector::doInMainThreadAfterFinished() +{ +} + const SymbolEntries &SymbolsCollector::symbols() const { return m_symbolEntries; diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.h b/src/tools/clangrefactoringbackend/source/symbolscollector.h index 70213555d6..beb610d190 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollector.h +++ b/src/tools/clangrefactoringbackend/source/symbolscollector.h @@ -54,6 +54,8 @@ public: void collectSymbols() override; + void doInMainThreadAfterFinished() override; + const SymbolEntries &symbols() const override; const SourceLocationEntries &sourceLocations() const override; const FilePathIds &sourceFiles() const override; diff --git a/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h index 540866630f..0b7e00509d 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h +++ b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h @@ -31,7 +31,7 @@ #include "sourcelocationentry.h" #include "usedmacro.h" -#include <filecontainerv2.h> +#include <processorinterface.h> #include <utils/smallstringvector.h> @@ -40,20 +40,10 @@ namespace ClangBackEnd { -class SymbolsCollectorInterface +class SymbolsCollectorInterface : public ProcessorInterface { public: - SymbolsCollectorInterface() = default; - virtual ~SymbolsCollectorInterface() = default; - SymbolsCollectorInterface(const SymbolsCollectorInterface &) = delete; - SymbolsCollectorInterface &operator=(const SymbolsCollectorInterface &) = delete; - virtual void setFile(FilePathId filePathId, const Utils::SmallStringVector &arguments) = 0; - - virtual void setUnsavedFiles(const V2::FileContainers &unsavedFiles) = 0; - - virtual void clear() = 0; - virtual void collectSymbols() = 0; virtual const SymbolEntries &symbols() const = 0; @@ -62,9 +52,6 @@ public: virtual const UsedMacros &usedMacros() const = 0; virtual const FileStatuses &fileStatuses() const = 0; virtual const SourceDependencies &sourceDependencies() const = 0; - - virtual bool isUsed() const = 0; - virtual void setIsUsed(bool isUsed) = 0; }; } // namespace ClangBackEnd |