forked from qt-creator/qt-creator
C++: Release more documents.
- fix memory leak in find-usages - do not retain snapshot in search history - when an editor is invisible for more than 2 minutes, release the backing snapshot Retaining snapshots will retain their documents, and if done for too long, the memory consumption might grow. This is especially the case when switching to a different kit (Qt version): in that case, the new versions of headers will be indexed, while the old ones stay around. Task-number: QTCREATORBUG-5583 Task-number: QTCREATORBUG-7645 Task-number: QTCREATORBUG-9842 Change-Id: I045eda1565e0a3fa702baeffaab9c12662f90289 Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
committed by
Nikolai Kosjar
parent
d58da4bd7e
commit
566be0995d
@@ -60,13 +60,12 @@ using namespace Utils;
|
||||
FunctionDeclDefLinkFinder::FunctionDeclDefLinkFinder(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
connect(&m_watcher, SIGNAL(finished()),
|
||||
this, SLOT(onFutureDone()));
|
||||
}
|
||||
|
||||
void FunctionDeclDefLinkFinder::onFutureDone()
|
||||
{
|
||||
QSharedPointer<FunctionDeclDefLink> link = m_watcher.result();
|
||||
QSharedPointer<FunctionDeclDefLink> link = m_watcher->result();
|
||||
m_watcher.reset();
|
||||
if (link) {
|
||||
link->linkSelection = m_scannedSelection;
|
||||
link->nameSelection = m_nameSelection;
|
||||
@@ -256,7 +255,9 @@ void FunctionDeclDefLinkFinder::startFindLinkAt(
|
||||
result->sourceFunctionDeclarator = funcDecl;
|
||||
|
||||
// handle the rest in a thread
|
||||
m_watcher.setFuture(QtConcurrent::run(&findLinkHelper, result, refactoringChanges));
|
||||
m_watcher.reset(new QFutureWatcher<QSharedPointer<FunctionDeclDefLink> >());
|
||||
connect(m_watcher.data(), SIGNAL(finished()), this, SLOT(onFutureDone()));
|
||||
m_watcher->setFuture(QtConcurrent::run(&findLinkHelper, result, refactoringChanges));
|
||||
}
|
||||
|
||||
FunctionDeclDefLink::FunctionDeclDefLink()
|
||||
@@ -270,10 +271,6 @@ FunctionDeclDefLink::FunctionDeclDefLink()
|
||||
targetFunctionDeclarator = 0;
|
||||
}
|
||||
|
||||
FunctionDeclDefLink::~FunctionDeclDefLink()
|
||||
{
|
||||
}
|
||||
|
||||
bool FunctionDeclDefLink::isValid() const
|
||||
{
|
||||
return !linkSelection.isNull();
|
||||
|
||||
@@ -67,7 +67,7 @@ private slots:
|
||||
private:
|
||||
QTextCursor m_scannedSelection;
|
||||
QTextCursor m_nameSelection;
|
||||
QFutureWatcher<QSharedPointer<FunctionDeclDefLink> > m_watcher;
|
||||
QScopedPointer<QFutureWatcher<QSharedPointer<FunctionDeclDefLink> > > m_watcher;
|
||||
};
|
||||
|
||||
class FunctionDeclDefLink
|
||||
@@ -75,8 +75,6 @@ class FunctionDeclDefLink
|
||||
Q_DECLARE_TR_FUNCTIONS(CppEditor::Internal::FunctionDeclDefLink)
|
||||
Q_DISABLE_COPY(FunctionDeclDefLink)
|
||||
public:
|
||||
~FunctionDeclDefLink();
|
||||
|
||||
class Marker {};
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
@@ -247,8 +247,9 @@ public:
|
||||
|
||||
CppFindReferences::CppFindReferences(CppModelManagerInterface *modelManager)
|
||||
: QObject(modelManager),
|
||||
_modelManager(modelManager)
|
||||
m_modelManager(modelManager)
|
||||
{
|
||||
connect(modelManager, SIGNAL(globalSnapshotChanged()), this, SLOT(flushDependencyTable()));
|
||||
}
|
||||
|
||||
CppFindReferences::~CppFindReferences()
|
||||
@@ -365,7 +366,7 @@ void CppFindReferences::findAll_helper(Find::SearchResult *search, CPlusPlus::Sy
|
||||
this, SLOT(openEditor(Find::SearchResultItem)));
|
||||
|
||||
Find::SearchResultWindow::instance()->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
|
||||
const CppModelManagerInterface::WorkingCopy workingCopy = _modelManager->workingCopy();
|
||||
const CppModelManagerInterface::WorkingCopy workingCopy = m_modelManager->workingCopy();
|
||||
QFuture<Usage> result;
|
||||
result = QtConcurrent::run(&find_helper, workingCopy, context, this, symbol);
|
||||
createWatcher(result, search);
|
||||
@@ -382,7 +383,7 @@ void CppFindReferences::onReplaceButtonClicked(const QString &text,
|
||||
{
|
||||
const QStringList fileNames = TextEditor::BaseFileFind::replaceAll(text, items, preserveCase);
|
||||
if (!fileNames.isEmpty()) {
|
||||
_modelManager->updateSourceFiles(fileNames);
|
||||
m_modelManager->updateSourceFiles(fileNames);
|
||||
Find::SearchResultWindow::instance()->hide();
|
||||
}
|
||||
}
|
||||
@@ -451,7 +452,7 @@ CPlusPlus::Symbol *CppFindReferences::findSymbol(const CppFindReferencesParamete
|
||||
|
||||
Document::Ptr newSymbolDocument = snapshot.document(symbolFile);
|
||||
// document is not parsed and has no bindings yet, do it
|
||||
QByteArray source = getSource(newSymbolDocument->fileName(), _modelManager->workingCopy());
|
||||
QByteArray source = getSource(newSymbolDocument->fileName(), m_modelManager->workingCopy());
|
||||
Document::Ptr doc =
|
||||
snapshot.preprocessedDocument(source, newSymbolDocument->fileName());
|
||||
doc->check();
|
||||
@@ -492,6 +493,7 @@ void CppFindReferences::searchFinished()
|
||||
if (search)
|
||||
search->finishSearch(watcher->isCanceled());
|
||||
m_watchers.remove(watcher);
|
||||
watcher->deleteLater();
|
||||
}
|
||||
|
||||
void CppFindReferences::cancel()
|
||||
@@ -651,8 +653,8 @@ void CppFindReferences::findMacroUses(const Macro ¯o, const QString &replace
|
||||
connect(search, SIGNAL(cancelled()), this, SLOT(cancel()));
|
||||
connect(search, SIGNAL(paused(bool)), this, SLOT(setPaused(bool)));
|
||||
|
||||
const Snapshot snapshot = _modelManager->snapshot();
|
||||
const CppModelManagerInterface::WorkingCopy workingCopy = _modelManager->workingCopy();
|
||||
const Snapshot snapshot = m_modelManager->snapshot();
|
||||
const CppModelManagerInterface::WorkingCopy workingCopy = m_modelManager->workingCopy();
|
||||
|
||||
// add the macro definition itself
|
||||
{
|
||||
@@ -691,6 +693,13 @@ DependencyTable CppFindReferences::updateDependencyTable(CPlusPlus::Snapshot sna
|
||||
return newDeps;
|
||||
}
|
||||
|
||||
void CppFindReferences::flushDependencyTable()
|
||||
{
|
||||
QMutexLocker locker(&m_depsLock);
|
||||
Q_UNUSED(locker);
|
||||
m_deps = DependencyTable();
|
||||
}
|
||||
|
||||
DependencyTable CppFindReferences::dependencyTable() const
|
||||
{
|
||||
QMutexLocker locker(&m_depsLock);
|
||||
|
||||
@@ -78,7 +78,10 @@ public:
|
||||
|
||||
CPlusPlus::DependencyTable updateDependencyTable(CPlusPlus::Snapshot snapshot);
|
||||
|
||||
private Q_SLOTS:
|
||||
public slots:
|
||||
void flushDependencyTable();
|
||||
|
||||
private slots:
|
||||
void displayResults(int first, int last);
|
||||
void searchFinished();
|
||||
void cancel();
|
||||
@@ -101,7 +104,7 @@ private:
|
||||
const CPlusPlus::Snapshot &snapshot, CPlusPlus::LookupContext *context);
|
||||
|
||||
private:
|
||||
QPointer<CppModelManagerInterface> _modelManager;
|
||||
QPointer<CppModelManagerInterface> m_modelManager;
|
||||
QMap<QFutureWatcher<CPlusPlus::Usage> *, QPointer<Find::SearchResult> > m_watchers;
|
||||
|
||||
mutable QMutex m_depsLock;
|
||||
|
||||
@@ -234,6 +234,11 @@ CppModelManager::CppModelManager(QObject *parent)
|
||||
, m_indexingSupporter(0)
|
||||
, m_enableGC(true)
|
||||
{
|
||||
connect(this, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)),
|
||||
this, SIGNAL(globalSnapshotChanged()));
|
||||
connect(this, SIGNAL(aboutToRemoveFiles(QStringList)),
|
||||
this, SIGNAL(globalSnapshotChanged()));
|
||||
|
||||
m_findReferences = new CppFindReferences(this);
|
||||
m_indexerEnabled = qgetenv("QTCREATOR_NO_CODE_INDEXER").isNull();
|
||||
|
||||
|
||||
@@ -279,6 +279,8 @@ signals:
|
||||
/// Other classes can use this to get notified when the \c ProjectExplorer has updated the parts.
|
||||
void projectPartsUpdated(ProjectExplorer::Project *project);
|
||||
|
||||
void globalSnapshotChanged();
|
||||
|
||||
public slots:
|
||||
// Documented in source file.
|
||||
virtual QFuture<void> updateSourceFiles(const QStringList &sourceFiles,
|
||||
|
||||
@@ -41,6 +41,7 @@ SnapshotUpdater::SnapshotUpdater(const QString &fileInEditor)
|
||||
, m_fileInEditor(fileInEditor)
|
||||
, m_editorDefinesChangedSinceLastUpdate(false)
|
||||
, m_usePrecompiledHeaders(false)
|
||||
, m_forceSnapshotInvalidation(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -62,6 +63,11 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy)
|
||||
|
||||
updateProjectPart();
|
||||
|
||||
if (m_forceSnapshotInvalidation) {
|
||||
invalidateSnapshot = true;
|
||||
m_forceSnapshotInvalidation = false;
|
||||
}
|
||||
|
||||
if (m_projectPart) {
|
||||
configFile += m_projectPart->defines;
|
||||
includePaths = m_projectPart->includePaths;
|
||||
@@ -186,6 +192,14 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy)
|
||||
}
|
||||
}
|
||||
|
||||
void SnapshotUpdater::releaseSnapshot()
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
m_snapshot = Snapshot();
|
||||
m_deps = DependencyTable();
|
||||
m_forceSnapshotInvalidation = true;
|
||||
}
|
||||
|
||||
Document::Ptr SnapshotUpdater::document() const
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
{ return m_fileInEditor; }
|
||||
|
||||
void update(CppModelManagerInterface::WorkingCopy workingCopy);
|
||||
void releaseSnapshot();
|
||||
|
||||
CPlusPlus::Document::Ptr document() const;
|
||||
CPlusPlus::Snapshot snapshot() const;
|
||||
@@ -81,6 +82,7 @@ private:
|
||||
CPlusPlus::Snapshot m_snapshot;
|
||||
CPlusPlus::DependencyTable m_deps;
|
||||
bool m_usePrecompiledHeaders;
|
||||
bool m_forceSnapshotInvalidation;
|
||||
};
|
||||
|
||||
} // namespace CppTools
|
||||
|
||||
@@ -115,6 +115,7 @@ CppEditorSupport::CppEditorSupport(CppModelManager *modelManager, BaseTextEditor
|
||||
, m_textEditor(textEditor)
|
||||
, m_updateDocumentInterval(UpdateDocumentDefaultInterval)
|
||||
, m_revision(0)
|
||||
, m_editorVisible(textEditor->widget()->isVisible())
|
||||
, m_cachedContentsEditorRevision(-1)
|
||||
, m_fileIsBeingReloaded(false)
|
||||
, m_initialized(false)
|
||||
@@ -152,6 +153,13 @@ CppEditorSupport::CppEditorSupport(CppModelManager *modelManager, BaseTextEditor
|
||||
connect(m_textEditor->document(), SIGNAL(reloadFinished(bool)),
|
||||
this, SLOT(onReloadFinished()));
|
||||
|
||||
connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor *)),
|
||||
this, SLOT(onCurrentEditorChanged()));
|
||||
m_editorGCTimer = new QTimer(this);
|
||||
m_editorGCTimer->setSingleShot(true);
|
||||
m_editorGCTimer->setInterval(EditorHiddenGCTimeout);
|
||||
connect(m_editorGCTimer, SIGNAL(timeout()), this, SLOT(releaseResources()));
|
||||
|
||||
updateDocument();
|
||||
}
|
||||
|
||||
@@ -460,6 +468,30 @@ void CppEditorSupport::updateEditorNow()
|
||||
editorWidget->setIfdefedOutBlocks(m_editorUpdates.ifdefedOutBlocks);
|
||||
}
|
||||
|
||||
void CppEditorSupport::onCurrentEditorChanged()
|
||||
{
|
||||
bool editorVisible = m_textEditor->widget()->isVisible();
|
||||
|
||||
if (m_editorVisible != editorVisible) {
|
||||
m_editorVisible = editorVisible;
|
||||
if (editorVisible) {
|
||||
m_editorGCTimer->stop();
|
||||
QMutexLocker locker(&m_lastSemanticInfoLock);
|
||||
if (!m_lastSemanticInfo.doc)
|
||||
updateDocumentNow();
|
||||
} else {
|
||||
m_editorGCTimer->start(EditorHiddenGCTimeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CppEditorSupport::releaseResources()
|
||||
{
|
||||
snapshotUpdater()->releaseSnapshot();
|
||||
QMutexLocker semanticLocker(&m_lastSemanticInfoLock);
|
||||
m_lastSemanticInfo = SemanticInfo();
|
||||
}
|
||||
|
||||
SemanticInfo::Source CppEditorSupport::currentSource(bool force)
|
||||
{
|
||||
int line = 0, column = 0;
|
||||
|
||||
@@ -148,6 +148,9 @@ private slots:
|
||||
void updateEditor();
|
||||
void updateEditorNow();
|
||||
|
||||
void onCurrentEditorChanged();
|
||||
void releaseResources();
|
||||
|
||||
private:
|
||||
struct EditorUpdates {
|
||||
EditorUpdates()
|
||||
@@ -160,7 +163,8 @@ private:
|
||||
|
||||
enum {
|
||||
UpdateDocumentDefaultInterval = 150,
|
||||
UpdateEditorInterval = 300
|
||||
UpdateEditorInterval = 300,
|
||||
EditorHiddenGCTimeout = 2 * 60 * 1000 // 2 minutes
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -178,6 +182,9 @@ private:
|
||||
unsigned m_revision;
|
||||
QFuture<void> m_documentParser;
|
||||
|
||||
QTimer *m_editorGCTimer;
|
||||
bool m_editorVisible;
|
||||
|
||||
// content caching
|
||||
mutable QMutex m_cachedContentsLock;
|
||||
mutable QByteArray m_cachedContents;
|
||||
|
||||
Reference in New Issue
Block a user