From 7583039b87c2908d40017ba1c245fed0b471c0f9 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 18 Jul 2013 10:57:19 +0200 Subject: [PATCH] CppTools: Do not call GC() more than necessary Currently GC() is invoked if - 5 CppEditors were closed or the last CppEditor was closed - a project is about to be removed - a session is about to be unloaded Thus, for the following use cases, too much GC() calls (can) happen: - File > Close All - Close All Projects and Editors - Changing the session Fixed by introducing a timer. Change-Id: I9c984d9de735fc8c6ee77a518e9fb5b63dba5881 Reviewed-by: Erik Verbruggen --- src/plugins/cpptools/cppmodelmanager.cpp | 24 ++++++++++++++++--- src/plugins/cpptools/cppmodelmanager.h | 7 +++++- src/plugins/cpptools/cppmodelmanager_test.cpp | 7 +++++- .../cpptools/modelmanagertesthelper.cpp | 16 +++++++++++++ src/plugins/cpptools/modelmanagertesthelper.h | 3 +++ 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index ed1ebd14794..cc1979d6b70 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -233,6 +233,10 @@ CppModelManager::CppModelManager(QObject *parent) ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance(); QTC_ASSERT(pe, return); + m_delayedGcTimer = new QTimer(this); + m_delayedGcTimer->setSingleShot(true); + connect(m_delayedGcTimer, SIGNAL(timeout()), this, SLOT(GC())); + ProjectExplorer::SessionManager *session = pe->session(); connect(session, SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(onProjectAdded(ProjectExplorer::Project*))); @@ -240,6 +244,9 @@ CppModelManager::CppModelManager(QObject *parent) connect(session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)), this, SLOT(onAboutToRemoveProject(ProjectExplorer::Project*))); + connect(session, SIGNAL(aboutToLoadSession(QString)), + this, SLOT(onAboutToLoadSession())); + connect(session, SIGNAL(aboutToUnloadSession(QString)), this, SLOT(onAboutToUnloadSession())); @@ -481,7 +488,7 @@ void CppModelManager::deleteCppEditorSupport(TextEditor::BaseTextEditor *textEdi ++numberOfClosedEditors; if (numberOfOpenEditors == 0 || numberOfClosedEditors == 5) { numberOfClosedEditors = 0; - GC(); + delayedGC(); } } @@ -663,6 +670,11 @@ void CppModelManager::onProjectAdded(ProjectExplorer::Project *) m_dirty = true; } +void CppModelManager::delayedGC() +{ + m_delayedGcTimer->start(500); +} + void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project) { do { @@ -671,6 +683,13 @@ void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project) m_projectToProjectsInfo.remove(project); } while (0); + delayedGC(); +} + +void CppModelManager::onAboutToLoadSession() +{ + if (m_delayedGcTimer->isActive()) + m_delayedGcTimer->stop(); GC(); } @@ -683,8 +702,6 @@ void CppModelManager::onAboutToUnloadSession() m_projectToProjectsInfo.clear(); m_dirty = true; } while (0); - - GC(); } void CppModelManager::onCoreAboutToClose() @@ -729,6 +746,7 @@ void CppModelManager::GC() // Announce removing files and replace the snapshot emit aboutToRemoveFiles(notReachableFiles); replaceSnapshot(newSnapshot); + emit gcFinished(); } void CppModelManager::finishedRefreshingSourceFiles(const QStringList &files) diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 7024ae1780d..a8ca3ee1a03 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -39,6 +39,7 @@ #include #include +#include namespace Core { class IEditor; } namespace TextEditor { class BaseTextEditorWidget; } @@ -77,7 +78,6 @@ public: virtual CPlusPlus::Snapshot snapshot() const; virtual Document::Ptr document(const QString &fileName) const; bool replaceDocument(Document::Ptr newDoc); - virtual void GC(); void emitDocumentUpdated(CPlusPlus::Document::Ptr doc); @@ -143,18 +143,22 @@ public: signals: void aboutToRemoveFiles(const QStringList &files); + void gcFinished(); // Needed for tests. public slots: virtual void updateModifiedSourceFiles(); + virtual void GC(); private slots: // This should be executed in the GUI thread. void onAboutToRemoveProject(ProjectExplorer::Project *project); + void onAboutToLoadSession(); void onAboutToUnloadSession(); void onCoreAboutToClose(); void onProjectAdded(ProjectExplorer::Project *project); private: + void delayedGC(); void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot); WorkingCopy buildWorkingCopyList(); @@ -207,6 +211,7 @@ private: CppFindReferences *m_findReferences; bool m_enableGC; + QTimer *m_delayedGcTimer; }; } // namespace Internal diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp index 669c086d529..7e649a9c014 100644 --- a/src/plugins/cpptools/cppmodelmanager_test.cpp +++ b/src/plugins/cpptools/cppmodelmanager_test.cpp @@ -472,6 +472,8 @@ void CppToolsPlugin::test_modelmanager_snapshot_after_two_projects() /// though it might not be actually generated in the build dir. void CppToolsPlugin::test_modelmanager_extraeditorsupport_uiFiles() { + ModelManagerTestHelper helper; + TestDataDirectory testDataDirectory(QLatin1String("testdata_guiproject1")); const QString projectFile = testDataDirectory.file(QLatin1String("testdata_guiproject1.pro")); @@ -515,13 +517,15 @@ void CppToolsPlugin::test_modelmanager_extraeditorsupport_uiFiles() // Close Project ProjectExplorer::SessionManager *sm = pe->session(); sm->removeProject(project); - ModelManagerTestHelper::verifyClean(); + helper.waitForFinishedGc(); } /// QTCREATORBUG-9828: Locator shows symbols of closed files /// Check: The garbage collector should be run if the last CppEditor is closed. void CppToolsPlugin::test_modelmanager_gc_if_last_cppeditor_closed() { + ModelManagerTestHelper helper; + TestDataDirectory testDataDirectory(QLatin1String("testdata_guiproject1")); const QString file = testDataDirectory.file(QLatin1String("main.cpp")); @@ -541,6 +545,7 @@ void CppToolsPlugin::test_modelmanager_gc_if_last_cppeditor_closed() // Close file/editor em->closeEditor(editor, /*askAboutModifiedEditors=*/ false); + helper.waitForFinishedGc(); // Check: File is removed from the snapshpt QVERIFY(!mm->workingCopy().contains(file)); diff --git a/src/plugins/cpptools/modelmanagertesthelper.cpp b/src/plugins/cpptools/modelmanagertesthelper.cpp index 46f2a917239..4d7590e130d 100644 --- a/src/plugins/cpptools/modelmanagertesthelper.cpp +++ b/src/plugins/cpptools/modelmanagertesthelper.cpp @@ -55,6 +55,7 @@ ModelManagerTestHelper::ModelManagerTestHelper(QObject *parent) : connect(this, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)), mm, SLOT(onAboutToRemoveProject(ProjectExplorer::Project*))); connect(this, SIGNAL(projectAdded(ProjectExplorer::Project*)), mm, SLOT(onProjectAdded(ProjectExplorer::Project*))); connect(mm, SIGNAL(sourceFilesRefreshed(QStringList)), this, SLOT(sourceFilesRefreshed(QStringList))); + connect(mm, SIGNAL(gcFinished()), this, SLOT(gcFinished())); cleanup(); verifyClean(); @@ -74,6 +75,9 @@ void ModelManagerTestHelper::cleanup() QList pies = mm->projectInfos(); foreach (const ProjectInfo &pie, pies) emit aboutToRemoveProject(pie.project().data()); + + if (!pies.isEmpty()) + waitForFinishedGc(); } void ModelManagerTestHelper::verifyClean() @@ -108,9 +112,21 @@ QStringList ModelManagerTestHelper::waitForRefreshedSourceFiles() return m_lastRefreshedSourceFiles; } +void ModelManagerTestHelper::waitForFinishedGc() +{ + m_gcFinished = false; + + while (!m_gcFinished) + QCoreApplication::processEvents(); +} void ModelManagerTestHelper::sourceFilesRefreshed(const QStringList &files) { m_lastRefreshedSourceFiles = files; m_refreshHappened = true; } + +void ModelManagerTestHelper::gcFinished() +{ + m_gcFinished = true; +} diff --git a/src/plugins/cpptools/modelmanagertesthelper.h b/src/plugins/cpptools/modelmanagertesthelper.h index b2b042c4452..d4ac671bc1b 100644 --- a/src/plugins/cpptools/modelmanagertesthelper.h +++ b/src/plugins/cpptools/modelmanagertesthelper.h @@ -84,6 +84,7 @@ public: Project *createProject(const QString &name); QStringList waitForRefreshedSourceFiles(); + void waitForFinishedGc(); signals: void aboutToRemoveProject(ProjectExplorer::Project *project); @@ -91,8 +92,10 @@ signals: public slots: void sourceFilesRefreshed(const QStringList &files); + void gcFinished(); private: + bool m_gcFinished; bool m_refreshHappened; QStringList m_lastRefreshedSourceFiles; };