From 260b6dadacbee3f450a1e962edd6b3eb3f5ba105 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Thu, 26 May 2016 14:55:49 -0700 Subject: [PATCH] Improved cancellability of indexer. Change-Id: I194e5b135f1f58501fb3345ca373feef23832c97 --- .../cdt/internal/core/util/Canceler.java | 33 +++++ .../cdt/internal/core/util/ICanceler.java | 20 ++- .../cdt/core/dom/IPDOMIndexerTask.java | 8 ++ .../core/pdom/AbstractIndexerTask.java | 133 ++++++++++-------- .../internal/core/pdom/PDOMIndexerJob.java | 16 +-- .../cdt/internal/core/pdom/PDOMWriter.java | 66 +++++---- .../core/pdom/indexer/PDOMRebuildTask.java | 6 + .../core/pdom/indexer/PDOMUpdateTask.java | 8 +- .../core/parser/ParserLogService.java | 19 ++- 9 files changed, 204 insertions(+), 105 deletions(-) create mode 100644 core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/util/Canceler.java diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/util/Canceler.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/util/Canceler.java new file mode 100644 index 00000000000..0e2bd86ec1d --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/util/Canceler.java @@ -0,0 +1,33 @@ +package org.eclipse.cdt.internal.core.util; + +/** + * A thread-safe implementation of {@link ICanceler} interface. + */ +public class Canceler implements ICanceler { + private ICancelable fCancelable; + private boolean canceled; + + @Override + public synchronized void setCancelable(ICancelable cancelable) { + fCancelable= cancelable; + checkCanceled(); + } + + @Override + public synchronized void setCanceled(boolean canceled) { + this.canceled = canceled; + checkCanceled(); + } + + @Override + public synchronized boolean isCanceled() { + return canceled; + } + + private synchronized void checkCanceled() { + if (fCancelable != null && canceled) { + fCancelable.cancel(); + fCancelable= null; + } + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/util/ICanceler.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/util/ICanceler.java index 7674b8d1d33..34a313ff9e6 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/util/ICanceler.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/util/ICanceler.java @@ -16,12 +16,24 @@ package org.eclipse.cdt.internal.core.util; * @since 5.0 */ public interface ICanceler { - /** - * Set the cancelable object. + * Sets the cancelable object. * * @param cancelable the cancelable object */ - void setCancelable(ICancelable cancelable); - + public void setCancelable(ICancelable cancelable); + + /** + * Sets the cancel state to the given value. The state will be propagated to the cancelable object + * if it was set. + * + * @param value {@code true} indicates that cancellation has been requested, + * {@code false} clears this flag + */ + public void setCanceled(boolean value); + + /** + * Checks if cancellation has been requested. + */ + public boolean isCanceled(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOMIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOMIndexerTask.java index 053e92fbbd7..cae22c27642 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOMIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOMIndexerTask.java @@ -33,6 +33,14 @@ public interface IPDOMIndexerTask { */ public void run(IProgressMonitor monitor) throws InterruptedException; + /** + * Notifies the task that it should stop executing at its earliest convenience. + * It's up to the task whether to react to this method or not. + * @noreference This method is not intended to be referenced by clients. + * @nooverride This default method is not intended to be re-implemented or extended by clients. + */ + public default void cancel() {} + /** * Returns the indexer the task belongs to. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java index 12bbc6b699b..95dcb4ad34f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java @@ -62,7 +62,6 @@ import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.ISignificantMacros; import org.eclipse.cdt.core.parser.IncludeExportPatterns; import org.eclipse.cdt.core.parser.IncludeFileContentProvider; -import org.eclipse.cdt.core.parser.ParserUtil; import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics; import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit; import org.eclipse.cdt.internal.core.index.FileContentKey; @@ -70,7 +69,9 @@ import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IWritableIndex; import org.eclipse.cdt.internal.core.index.IndexBasedFileContentProvider; +import org.eclipse.cdt.internal.core.model.DebugLogConstants; import org.eclipse.cdt.internal.core.parser.IMacroDictionary; +import org.eclipse.cdt.internal.core.parser.ParserLogService; import org.eclipse.cdt.internal.core.parser.ParserSettings2; import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider; import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider.DependsOnOutdatedFileException; @@ -80,8 +81,10 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.osgi.util.NLS; /** @@ -333,7 +336,6 @@ public abstract class AbstractIndexerTask extends PDOMWriter { private final Deque fUrgentTasks; boolean fTaskCompleted; private IndexerProgress fInfo= new IndexerProgress(); - private IProgressMonitor fProgressMonitor; public AbstractIndexerTask(Object[] filesToUpdate, Object[] filesToRemove, IndexerInputAdapter resolver, boolean fastIndexer) { @@ -448,7 +450,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } protected IParserLogService getLogService() { - return ParserUtil.getParserLogService(); + return new ParserLogService(DebugLogConstants.PARSER, fCancelState); } protected void logError(IStatus s) { @@ -514,7 +516,6 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } public final void runTask(IProgressMonitor monitor) throws InterruptedException { - fProgressMonitor = monitor; try { if (!fIndexFilesWithoutConfiguration) { fIndexHeadersWithoutContext= UnusedHeaderStrategy.skip; @@ -538,22 +539,25 @@ public abstract class AbstractIndexerTask extends PDOMWriter { try { try { + SubMonitor progress = SubMonitor.convert(monitor, 20); // Split into sources and headers, remove excluded sources. HashMap> files= new HashMap<>(); final ArrayList indexFilesToRemove= new ArrayList<>(); - extractFiles(files, indexFilesToRemove, monitor); + extractFiles(files, indexFilesToRemove, progress.split(1)); - setResume(true); + setResume(true, progress.split(1)); // Remove files from index - removeFilesInIndex(fFilesToRemove, indexFilesToRemove, monitor); + removeFilesInIndex(fFilesToRemove, indexFilesToRemove, progress.split(1)); HashMap> moreFiles= null; while (true) { - for (int linkageID : getLinkagesToParse()) { + int[] linkageIDs = getLinkagesToParse(); + progress.setWorkRemaining((linkageIDs.length + 2) * 2); + for (int linkageID : linkageIDs) { final List filesForLinkage = files.get(linkageID); if (filesForLinkage != null) { - parseLinkage(linkageID, filesForLinkage, monitor); + parseLinkage(linkageID, filesForLinkage, progress.split(1)); for (Iterator it = fOneLinkageTasks.values().iterator(); it.hasNext();) { LocationTask task = it.next(); if (task.isCompleted()) @@ -598,13 +602,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter { fForceNumberFiles = urgentTask.fForceNumberFiles; fFilesToRemove = urgentTask.fFilesToRemove; incrementRequestedFilesCount(fFilesToUpdate.length + fFilesToRemove.size()); - extractFiles(files, indexFilesToRemove, monitor); - removeFilesInIndex(fFilesToRemove, indexFilesToRemove, monitor); + extractFiles(files, indexFilesToRemove, progress.split(1)); + removeFilesInIndex(fFilesToRemove, indexFilesToRemove, progress.split(1)); } } - if (!monitor.isCanceled()) { - setResume(false); - } + setResume(false, progress.split(1)); } finally { fIndex.flush(); } @@ -617,12 +619,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter { synchronized (this) { fTaskCompleted = true; } - fProgressMonitor = null; } } - private void setResume(boolean value) throws InterruptedException, CoreException { - fIndex.acquireWriteLock(fProgressMonitor); + private void setResume(boolean value, IProgressMonitor monitor) throws InterruptedException, CoreException { + fIndex.acquireWriteLock(monitor); try { fIndex.getWritableFragment().setProperty(IIndexFragment.PROPERTY_RESUME_INDEXER, String.valueOf(value)); } finally { @@ -640,10 +641,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter { int count= 0; int forceFirst= fForceNumberFiles; BitSet linkages= new BitSet(); + SubMonitor progress = SubMonitor.convert(monitor, fFilesToUpdate.length); for (final Object tu : fFilesToUpdate) { - if (monitor.isCanceled()) - return; - + progress.split(1); final boolean force= forceAll || --forceFirst >= 0; final IIndexFileLocation ifl= fResolver.resolveFile(tu); if (ifl == null) @@ -828,12 +828,12 @@ public abstract class AbstractIndexerTask extends PDOMWriter { private void removeFilesInIndex(List filesToRemove, List indexFilesToRemove, IProgressMonitor monitor) throws InterruptedException, CoreException { if (!filesToRemove.isEmpty() || !indexFilesToRemove.isEmpty()) { - fIndex.acquireWriteLock(fProgressMonitor); + SubMonitor progress = + SubMonitor.convert(monitor, 1 + filesToRemove.size() + indexFilesToRemove.size()); + fIndex.acquireWriteLock(progress.split(1)); try { for (Object tu : filesToRemove) { - if (monitor.isCanceled()) { - return; - } + progress.split(1); IIndexFileLocation ifl= fResolver.resolveFile(tu); if (ifl == null) continue; @@ -844,9 +844,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { incrementRequestedFilesCount(-1); } for (IIndexFragmentFile ifile : indexFilesToRemove) { - if (monitor.isCanceled()) { - return; - } + progress.split(1); fIndex.clearFile(ifile); incrementRequestedFilesCount(-1); } @@ -863,6 +861,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { if (map == null || files == null || files.isEmpty()) return; + SubMonitor progress = SubMonitor.convert(monitor, files.size() + 1); int maxPriority = Integer.MIN_VALUE; int minPriority = Integer.MAX_VALUE; Map> filesByPriority = new HashMap<>(); @@ -893,11 +892,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter { if (locTask == null || locTask.isCompleted()) { it.remove(); } else if (locTask.fKind == UpdateKind.REQUIRED_SOURCE) { - if (monitor.isCanceled() || hasUrgentTasks()) + if (hasUrgentTasks()) return; final Object tu = locTask.fTu; final IScannerInfo scannerInfo = getScannerInfo(linkageID, tu); - parseFile(tu, getLanguage(tu, linkageID), ifl, scannerInfo, null, monitor); + parseFile(tu, getLanguage(tu, linkageID), ifl, scannerInfo, null, progress.split(1)); } } @@ -910,10 +909,10 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } else { for (FileVersionTask versionTask : locTask.fVersionTasks) { if (versionTask.fOutdated) { - if (monitor.isCanceled() || hasUrgentTasks()) + if (hasUrgentTasks()) return; parseVersionInContext(linkageID, map, ifl, versionTask, locTask.fTu, - new LinkedHashSet(), monitor); + new LinkedHashSet(), progress.split(1)); } } } @@ -927,11 +926,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter { it.remove(); } else { if (locTask.needsVersion()) { - if (monitor.isCanceled() || hasUrgentTasks()) + if (hasUrgentTasks()) return; final Object tu = locTask.fTu; final IScannerInfo scannerInfo= getScannerInfo(linkageID, tu); - parseFile(tu, getLanguage(tu, linkageID), ifl, scannerInfo, null, monitor); + parseFile(tu, getLanguage(tu, linkageID), ifl, scannerInfo, null, progress.split(1)); if (locTask.isCompleted()) it.remove(); @@ -940,13 +939,14 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } // Delete remaining files. - fIndex.acquireWriteLock(fProgressMonitor); + fIndex.acquireWriteLock(progress.split(1)); try { for (IIndexFileLocation ifl : filesAtPriority) { LocationTask locTask = map.find(ifl); if (locTask != null && !locTask.isCompleted()) { if (!locTask.needsVersion()) { - if (monitor.isCanceled() || hasUrgentTasks()) + progress.split(1); + if (hasUrgentTasks()) return; Iterator it= locTask.fVersionTasks.iterator(); while (it.hasNext()) { @@ -973,10 +973,12 @@ public abstract class AbstractIndexerTask extends PDOMWriter { IProgressMonitor monitor) throws CoreException, InterruptedException { final IIndexFragmentFile headerFile = versionTask.fIndexFile; + SubMonitor progress = SubMonitor.convert(monitor, 10); final int safeguardSize= safeGuard.size(); while (true) { + progress.setWorkRemaining(10); // Look for a context and parse the file. - IIndexFragmentFile ctxFile = findContextFile(linkageID, map, versionTask, safeGuard, monitor); + IIndexFragmentFile ctxFile = findContextFile(linkageID, map, versionTask, safeGuard, progress.split(1)); if (ctxFile == null || ctxFile == headerFile) return; @@ -990,23 +992,25 @@ public abstract class AbstractIndexerTask extends PDOMWriter { Set dependencies= null; boolean done= false; while (!done) { + progress.setWorkRemaining(9); done= true; - DependsOnOutdatedFileException d= parseFile(tu, language, ifl, scannerInfo, ctx, monitor); + DependsOnOutdatedFileException d= parseFile(tu, language, ifl, scannerInfo, ctx, progress.split(1)); if (d != null) { - // File was not parsed, because there is a dependency that needs to be - // handled before. + // File was not parsed, because there is a dependency that needs to be handled before. if (dependencies == null) dependencies= new HashSet<>(); if (dependencies.add(d.fIndexFile)) { - if (parseFile(d.fTu, language, d.fIndexFile.getLocation(), scannerInfo, new FileContext(ctxFile, d.fIndexFile), monitor) == null) + if (parseFile(d.fTu, language, d.fIndexFile.getLocation(), scannerInfo, + new FileContext(ctxFile, d.fIndexFile), progress.split(1)) == null) { done= false; + } } } } if (!ctx.fLostPragmaOnceSemantics) return; - // Try the next context + // Try the next context. restoreSet(safeGuard, safeguardSize); } } @@ -1057,9 +1061,10 @@ public abstract class AbstractIndexerTask extends PDOMWriter { // Handle the context first. parseVersionInContext(linkageID, map, ctxIfl, ctxVersionTask, ctxTask.fTu, safeGuard, monitor); - if (ctxVersionTask.fOutdated // This is unexpected. - || !versionTask.fOutdated) // Our file was parsed. + if (ctxVersionTask.fOutdated // This is unexpected. + || !versionTask.fOutdated) { // Our file was parsed. return null; + } // The file is no longer a context, look for a different one. nextCtx= ctxFile; @@ -1070,8 +1075,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } private DependsOnOutdatedFileException parseFile(Object tu, AbstractLanguage lang, - IIndexFileLocation ifl, IScannerInfo scanInfo, FileContext ctx, IProgressMonitor pm) + IIndexFileLocation ifl, IScannerInfo scanInfo, FileContext ctx, IProgressMonitor monitor) throws CoreException, InterruptedException { + SubMonitor progress = SubMonitor.convert(monitor, 21); boolean resultCacheCleared = false; IPath path= getLabel(ifl); Throwable th= null; @@ -1079,14 +1085,15 @@ public abstract class AbstractIndexerTask extends PDOMWriter { if (fShowActivity) { trace("Indexer: parsing " + path.toOSString()); //$NON-NLS-1$ } - pm.subTask(getMessage(MessageKind.parsingFileTask, + progress.subTask(getMessage(MessageKind.parsingFileTask, path.lastSegment(), path.removeLastSegments(1).toString())); FileContent codeReader= fResolver.getCodeReader(tu); final boolean isSource = fResolver.isSourceUnit(tu); long start= System.currentTimeMillis(); ASTTypeUtil.startTranslationUnit(); - IASTTranslationUnit ast= createAST(lang, codeReader, scanInfo, isSource, fASTOptions, ctx, pm); + IASTTranslationUnit ast= + createAST(lang, codeReader, scanInfo, isSource, fASTOptions, ctx, progress.split(10)); fStatistics.fParsingTime += System.currentTimeMillis() - start; if (ast == null) { ++fStatistics.fTooManyTokensCount; @@ -1094,9 +1101,10 @@ public abstract class AbstractIndexerTask extends PDOMWriter { // Give the new AST a chance to recognize its translation unit before it is written // to the index. ((ASTTranslationUnit) ast).setOriginatingTranslationUnit((ITranslationUnit) tu); - writeToIndex(lang.getLinkageID(), ast, codeReader, ctx, pm); + writeToIndex(lang.getLinkageID(), ast, codeReader, ctx, progress.split(10)); resultCacheCleared = true; // The cache was cleared while writing to the index. } + } catch (OperationCanceledException e) { } catch (RuntimeException e) { final Throwable cause = e.getCause(); if (cause instanceof DependsOnOutdatedFileException) @@ -1118,7 +1126,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { if (!resultCacheCleared) { // If the result cache has not been cleared, clear it under a write lock to reduce // interference with index readers. - fIndex.acquireWriteLock(fProgressMonitor); + fIndex.acquireWriteLock(progress.split(1)); try { fIndex.clearResultCache(); } finally { @@ -1197,7 +1205,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { private final IASTTranslationUnit createAST(AbstractLanguage language, FileContent codeReader, IScannerInfo scanInfo, boolean isSource, int options, - FileContext ctx, IProgressMonitor pm) throws CoreException { + FileContext ctx, IProgressMonitor monitor) throws CoreException { if (codeReader == null) { return null; } @@ -1233,8 +1241,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter { IASTTranslationUnit ast= language.getASTTranslationUnit(codeReader, scanInfo, fCodeReaderFactory, fIndex, options, getLogService()); - if (pm.isCanceled()) { - return null; + if (monitor.isCanceled()) { + throw new OperationCanceledException(); } return ast; } @@ -1248,7 +1256,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } private void writeToIndex(final int linkageID, IASTTranslationUnit ast, FileContent codeReader, - FileContext ctx, IProgressMonitor pm) throws CoreException, InterruptedException { + FileContext ctx, IProgressMonitor monitor) throws CoreException, InterruptedException { + SubMonitor progress = SubMonitor.convert(monitor, 3); HashSet enteredFiles= new HashSet<>(); ArrayList orderedFileKeys= new ArrayList<>(); @@ -1279,9 +1288,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter { int storageLinkageID = process(ast, data); if (storageLinkageID != ILinkage.NO_LINKAGE_ID) { IASTComment[] comments = ast.getComments(); - data.fReplacementHeaders = extractReplacementHeaders(comments, pm); + data.fReplacementHeaders = extractReplacementHeaders(comments, progress.split(1)); - addSymbols(data, storageLinkageID, ctx, pm); + addSymbols(data, storageLinkageID, ctx, progress.split(1)); // Update task markers. if (fTodoTaskUpdater != null) { @@ -1294,11 +1303,13 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } // Contributed processors now have an opportunity to examine the AST. - for (IPDOMASTProcessor processor : PDOMASTProcessorManager.getProcessors(ast)) { + List processors = PDOMASTProcessorManager.getProcessors(ast); + progress.setWorkRemaining(processors.size()); + for (IPDOMASTProcessor processor : processors) { data = new PDOMWriter.Data(ast, fileKeys, fIndex); storageLinkageID = processor.process(ast, data); if (storageLinkageID != ILinkage.NO_LINKAGE_ID) - addSymbols(data, storageLinkageID, ctx, pm); + addSymbols(data, storageLinkageID, ctx, progress.split(1)); } } catch (CoreException | RuntimeException | Error e) { // Avoid parsing files again, that caused an exception to be thrown. @@ -1308,7 +1319,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { } private void collectOrderedFileKeys(final int linkageID, IASTInclusionNode inclusion, - HashSet enteredFiles, ArrayList orderedFileKeys) throws CoreException { + Set enteredFiles, List orderedFileKeys) throws CoreException { final IASTPreprocessorIncludeStatement include= inclusion.getIncludeDirective(); if (include.createsAST()) { final IIndexFileLocation ifl= fResolver.resolveASTPath(include.getPath()); @@ -1352,7 +1363,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { * * @return replacement headers keyed by file paths */ - private Map extractReplacementHeaders(IASTComment[] comments, IProgressMonitor pm) { + private Map extractReplacementHeaders(IASTComment[] comments, IProgressMonitor monitor) { Map replacementHeaders = new HashMap<>(); StringBuilder text = new StringBuilder(); IASTFileLocation carryoverLocation = null; @@ -1405,8 +1416,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { // include "header" if (text.charAt(matcher.end()) == ',' && isWhitespace(text, matcher.end() + 1, text.length())) { - // Defer processing until the next comment, which will be appended to this - // one. + // Defer processing until the next comment, which will be appended to this one. carryoverLocation = location; } } @@ -1442,7 +1452,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter { return fc; } - IIndexFragmentFile selectIndexFile(int linkageID, IIndexFileLocation ifl, ISignificantMacros sigMacros) throws CoreException { + IIndexFragmentFile selectIndexFile(int linkageID, IIndexFileLocation ifl, ISignificantMacros sigMacros) + throws CoreException { LinkageTask map = findRequestMap(linkageID); if (map != null) { LocationTask locTask= map.find(ifl); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java index fc1d246b4ef..9574205c673 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMIndexerJob.java @@ -58,10 +58,14 @@ public class PDOMIndexerJob extends Job { @Override protected void canceling() { // Speed up cancellation by notifying the waiting thread. - synchronized(this) { + synchronized (this) { fCancelled= true; notify(); } + synchronized (taskMutex) { + if (currentTask != null) + currentTask.cancel(); + } } } @@ -159,15 +163,7 @@ public class PDOMIndexerJob extends Job { } } while (currentTask != null); return Status.OK_STATUS; - } catch (RuntimeException e) { - CCorePlugin.log(e); - pdomManager.cancelledIndexerJob(true); - synchronized (taskMutex) { - currentTask= null; - taskMutex.notifyAll(); - } - throw e; - } catch (Error e) { + } catch (RuntimeException | Error e) { CCorePlugin.log(e); pdomManager.cancelledIndexerJob(true); synchronized (taskMutex) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java index 42f005fb58b..c2aed92bfae 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java @@ -67,11 +67,15 @@ import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation; import org.eclipse.cdt.internal.core.parser.scanner.LocationMap; import org.eclipse.cdt.internal.core.pdom.dom.PDOMASTAdapter; import org.eclipse.cdt.internal.core.pdom.indexer.IndexerASTVisitor; +import org.eclipse.cdt.internal.core.util.Canceler; +import org.eclipse.cdt.internal.core.util.ICanceler; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.osgi.util.NLS; /** @@ -203,6 +207,7 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { protected boolean fShowActivity; protected final IndexerStatistics fStatistics; protected final IndexerInputAdapter fResolver; + protected final ICanceler fCancelState = new Canceler(); private int fSkipReferences= SKIP_NO_REFERENCES; @@ -256,7 +261,7 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { * the index after your last write operation. */ final protected void addSymbols(Data data, int storageLinkageID, FileContext ctx, - IProgressMonitor pm) throws InterruptedException, CoreException { + IProgressMonitor monitor) throws InterruptedException, CoreException { if (data.isEmpty() || storageLinkageID == ILinkage.NO_LINKAGE_ID) return; @@ -266,11 +271,12 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { fShowSyntaxProblems= true; } + SubMonitor progress = SubMonitor.convert(monitor, 2); // Name resolution. - resolveNames(data, pm); + resolveNames(data, progress.split(1)); // Index update. - storeSymbolsInIndex(data, storageLinkageID, ctx, pm); + storeSymbolsInIndex(data, storageLinkageID, ctx, progress.split(1)); if (!data.fStatuses.isEmpty()) { List statuses = data.fStatuses; @@ -294,26 +300,24 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { } } - private void storeSymbolsInIndex(final Data data, int storageLinkageID, FileContext ctx, IProgressMonitor pm) - throws InterruptedException, CoreException { + private void storeSymbolsInIndex(final Data data, int storageLinkageID, FileContext ctx, + IProgressMonitor monitor) throws InterruptedException, CoreException { final IIndexFragmentFile newFile= ctx == null ? null : ctx.fNewFile; + SubMonitor progress = SubMonitor.convert(monitor, data.fSelectedFiles.length * 10); for (int i= 0; i < data.fSelectedFiles.length; i++) { - if (pm.isCanceled()) - return; - final FileInAST fileInAST= data.fSelectedFiles[i]; if (fileInAST != null) { if (fShowActivity) { trace("Indexer: adding " + fileInAST.fileContentKey.getLocation().getURI()); //$NON-NLS-1$ } Throwable th= null; - YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, false, pm); + YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, false, progress.split(1)); lock.acquire(); try { final boolean isReplacement= ctx != null && fileInAST.includeStatement == null; IIndexFragmentFile ifile= null; if (!isReplacement || newFile == null) { - ifile= storeFileInIndex(data, fileInAST, storageLinkageID, lock); + ifile= storeFileInIndex(data, fileInAST, storageLinkageID, lock, progress.split(9)); reportFileWrittenToIndex(fileInAST, ifile); } @@ -321,8 +325,7 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { if (ifile == null) ifile= newFile; if (ctx != null && !ctx.fOldFile.equals(ifile) && ifile != null) { - if (ctx.fOldFile.hasPragmaOnceSemantics() && - !ifile.hasPragmaOnceSemantics()) { + if (ctx.fOldFile.hasPragmaOnceSemantics() && !ifile.hasPragmaOnceSemantics()) { data.fIndex.transferContext(ctx.fOldFile, ifile); ctx.fLostPragmaOnceSemantics= true; } else { @@ -330,16 +333,11 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { } } } - } catch (RuntimeException e) { - th= e; - } catch (StackOverflowError e) { - th= e; - } catch (AssertionError e) { + } catch (RuntimeException | StackOverflowError | AssertionError e) { th= e; } finally { - // Because the caller holds a read-lock, the result cache of the index is never - // cleared. Before releasing the lock for the last time in this AST, we clear - // the result cache. + // Because the caller holds a read-lock, the result cache of the index is never cleared. + // Before releasing the lock for the last time in this AST, we clear the result cache. if (i == data.fSelectedFiles.length - 1) { data.fIndex.clearResultCache(); } @@ -354,19 +352,19 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { } } - private void resolveNames(Data data, IProgressMonitor pm) { + private void resolveNames(Data data, IProgressMonitor monitor) { long start= System.currentTimeMillis(); + SubMonitor progress = SubMonitor.convert(monitor, data.fSelectedFiles.length); for (FileInAST file : data.fSelectedFiles) { - if (pm.isCanceled()) { - return; - } Symbols symbols= data.fSymbolMap.get(file.includeStatement); final ArrayList names= symbols.fNames; + SubMonitor progress2 = SubMonitor.convert(progress, names.size()); boolean reported= false; for (Iterator j = names.iterator(); j.hasNext();) { final IASTName[] na= j.next(); final IASTName name = na[0]; + progress2.split(1); if (name != null) { // should not be null, just be defensive. Throwable th= null; try { @@ -467,8 +465,12 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { // Names. final IndexerASTVisitor visitor = new IndexerASTVisitor((fSkipReferences & SKIP_IMPLICIT_REFERENCES) == 0) { + private int cancelationCheckThrottler; + @Override public void visit(IASTName name, IASTName caller) { + checkForCancellation(); + if (fSkipReferences == SKIP_ALL_REFERENCES) { if (name.isReference()) { if (!isRequiredReference(name)) { @@ -487,6 +489,16 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { } } } + + private void checkForCancellation() { + if (cancelationCheckThrottler <= 0) { + if (fCancelState.isCanceled()) + throw new OperationCanceledException(); + cancelationCheckThrottler = 1000; + } else { + cancelationCheckThrottler--; + } + } }; ast.accept(visitor); @@ -558,7 +570,7 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { } private IIndexFragmentFile storeFileInIndex(Data data, FileInAST astFile, int storageLinkageID, - YieldableIndexLock lock) throws CoreException, InterruptedException { + YieldableIndexLock lock, IProgressMonitor monitor) throws CoreException, InterruptedException { final IWritableIndex index = data.fIndex; IIndexFragmentFile file; // We create a temporary PDOMFile with zero timestamp, add names to it, then replace @@ -686,4 +698,8 @@ public abstract class PDOMWriter implements IPDOMASTProcessor { protected IStatus createStatus(String msg, Throwable e) { return CCorePlugin.createStatus(msg, e); } + + public void cancel() { + fCancelState.setCanceled(true); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMRebuildTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMRebuildTask.java index f1213fc6a31..ddf5d12a8e5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMRebuildTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMRebuildTask.java @@ -137,4 +137,10 @@ public class PDOMRebuildTask implements IPDOMIndexerTask { public synchronized boolean acceptUrgentTask(IPDOMIndexerTask task) { return fDelegate != null && fDelegate.acceptUrgentTask(task); } + + @Override + public void cancel() { + if (fDelegate != null) + fDelegate.cancel(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java index 26fa99cd9c1..06a8181a065 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMUpdateTask.java @@ -281,6 +281,12 @@ public class PDOMUpdateTask implements IPDOMIndexerTask { } public void setTranslationUnitSelection(List filesAndFolders) { - fFilesAndFolders= new ArrayList(filesAndFolders); + fFilesAndFolders= new ArrayList<>(filesAndFolders); + } + + @Override + public void cancel() { + if (fDelegate != null) + fDelegate.cancel(); } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/parser/ParserLogService.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/parser/ParserLogService.java index 24d3ec79ca3..7c09ff9db23 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/parser/ParserLogService.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/parser/ParserLogService.java @@ -17,6 +17,7 @@ import org.eclipse.cdt.core.ICLogConstants; import org.eclipse.cdt.core.parser.AbstractParserLogService; import org.eclipse.cdt.internal.core.model.DebugLogConstants; import org.eclipse.cdt.internal.core.model.Util; +import org.eclipse.cdt.internal.core.util.Canceler; import org.eclipse.cdt.internal.core.util.ICancelable; import org.eclipse.cdt.internal.core.util.ICanceler; import org.eclipse.core.runtime.Platform; @@ -31,10 +32,12 @@ public class ParserLogService extends AbstractParserLogService implements ICance private final ICanceler fCanceler; public ParserLogService(DebugLogConstants constant) { - this(constant, null); + this(constant, new Canceler()); } public ParserLogService(DebugLogConstants constant, ICanceler canceler) { + if (canceler == null) + throw new NullPointerException(); topic = constant; if (CCorePlugin.getDefault() == null) { fIsTracingExceptions= false; @@ -79,8 +82,16 @@ public class ParserLogService extends AbstractParserLogService implements ICance @Override public void setCancelable(ICancelable cancelable) { - if (fCanceler != null) { - fCanceler.setCancelable(cancelable); - } + fCanceler.setCancelable(cancelable); + } + + @Override + public void setCanceled(boolean value) { + fCanceler.setCanceled(value); + } + + @Override + public boolean isCanceled() { + return fCanceler.isCanceled(); } }