1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-01 06:05:24 +02:00

Improved cancellability of indexer.

Change-Id: I194e5b135f1f58501fb3345ca373feef23832c97
This commit is contained in:
Sergey Prigogin 2016-05-26 14:55:49 -07:00 committed by Gerrit Code Review @ Eclipse.org
parent d4a911baa8
commit 260b6dadac
9 changed files with 204 additions and 105 deletions

View file

@ -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;
}
}
}

View file

@ -16,12 +16,24 @@ package org.eclipse.cdt.internal.core.util;
* @since 5.0 * @since 5.0
*/ */
public interface ICanceler { public interface ICanceler {
/** /**
* Set the cancelable object. * Sets the cancelable object.
* *
* @param cancelable 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();
} }

View file

@ -33,6 +33,14 @@ public interface IPDOMIndexerTask {
*/ */
public void run(IProgressMonitor monitor) throws InterruptedException; 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. * Returns the indexer the task belongs to.
*/ */

View file

@ -62,7 +62,6 @@ import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ISignificantMacros; import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IncludeExportPatterns; import org.eclipse.cdt.core.parser.IncludeExportPatterns;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider; 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.IIncludeFileResolutionHeuristics;
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
import org.eclipse.cdt.internal.core.index.FileContentKey; 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.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IWritableIndex; import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.index.IndexBasedFileContentProvider; 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.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.ParserLogService;
import org.eclipse.cdt.internal.core.parser.ParserSettings2; 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;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider.DependsOnOutdatedFileException; 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.IPath;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.osgi.util.NLS; import org.eclipse.osgi.util.NLS;
/** /**
@ -333,7 +336,6 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
private final Deque<AbstractIndexerTask> fUrgentTasks; private final Deque<AbstractIndexerTask> fUrgentTasks;
boolean fTaskCompleted; boolean fTaskCompleted;
private IndexerProgress fInfo= new IndexerProgress(); private IndexerProgress fInfo= new IndexerProgress();
private IProgressMonitor fProgressMonitor;
public AbstractIndexerTask(Object[] filesToUpdate, Object[] filesToRemove, public AbstractIndexerTask(Object[] filesToUpdate, Object[] filesToRemove,
IndexerInputAdapter resolver, boolean fastIndexer) { IndexerInputAdapter resolver, boolean fastIndexer) {
@ -448,7 +450,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
} }
protected IParserLogService getLogService() { protected IParserLogService getLogService() {
return ParserUtil.getParserLogService(); return new ParserLogService(DebugLogConstants.PARSER, fCancelState);
} }
protected void logError(IStatus s) { protected void logError(IStatus s) {
@ -514,7 +516,6 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
} }
public final void runTask(IProgressMonitor monitor) throws InterruptedException { public final void runTask(IProgressMonitor monitor) throws InterruptedException {
fProgressMonitor = monitor;
try { try {
if (!fIndexFilesWithoutConfiguration) { if (!fIndexFilesWithoutConfiguration) {
fIndexHeadersWithoutContext= UnusedHeaderStrategy.skip; fIndexHeadersWithoutContext= UnusedHeaderStrategy.skip;
@ -538,22 +539,25 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
try { try {
try { try {
SubMonitor progress = SubMonitor.convert(monitor, 20);
// Split into sources and headers, remove excluded sources. // Split into sources and headers, remove excluded sources.
HashMap<Integer, List<IIndexFileLocation>> files= new HashMap<>(); HashMap<Integer, List<IIndexFileLocation>> files= new HashMap<>();
final ArrayList<IIndexFragmentFile> indexFilesToRemove= new ArrayList<>(); final ArrayList<IIndexFragmentFile> indexFilesToRemove= new ArrayList<>();
extractFiles(files, indexFilesToRemove, monitor); extractFiles(files, indexFilesToRemove, progress.split(1));
setResume(true); setResume(true, progress.split(1));
// Remove files from index // Remove files from index
removeFilesInIndex(fFilesToRemove, indexFilesToRemove, monitor); removeFilesInIndex(fFilesToRemove, indexFilesToRemove, progress.split(1));
HashMap<Integer, List<IIndexFileLocation>> moreFiles= null; HashMap<Integer, List<IIndexFileLocation>> moreFiles= null;
while (true) { while (true) {
for (int linkageID : getLinkagesToParse()) { int[] linkageIDs = getLinkagesToParse();
progress.setWorkRemaining((linkageIDs.length + 2) * 2);
for (int linkageID : linkageIDs) {
final List<IIndexFileLocation> filesForLinkage = files.get(linkageID); final List<IIndexFileLocation> filesForLinkage = files.get(linkageID);
if (filesForLinkage != null) { if (filesForLinkage != null) {
parseLinkage(linkageID, filesForLinkage, monitor); parseLinkage(linkageID, filesForLinkage, progress.split(1));
for (Iterator<LocationTask> it = fOneLinkageTasks.values().iterator(); it.hasNext();) { for (Iterator<LocationTask> it = fOneLinkageTasks.values().iterator(); it.hasNext();) {
LocationTask task = it.next(); LocationTask task = it.next();
if (task.isCompleted()) if (task.isCompleted())
@ -598,13 +602,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
fForceNumberFiles = urgentTask.fForceNumberFiles; fForceNumberFiles = urgentTask.fForceNumberFiles;
fFilesToRemove = urgentTask.fFilesToRemove; fFilesToRemove = urgentTask.fFilesToRemove;
incrementRequestedFilesCount(fFilesToUpdate.length + fFilesToRemove.size()); incrementRequestedFilesCount(fFilesToUpdate.length + fFilesToRemove.size());
extractFiles(files, indexFilesToRemove, monitor); extractFiles(files, indexFilesToRemove, progress.split(1));
removeFilesInIndex(fFilesToRemove, indexFilesToRemove, monitor); removeFilesInIndex(fFilesToRemove, indexFilesToRemove, progress.split(1));
} }
} }
if (!monitor.isCanceled()) { setResume(false, progress.split(1));
setResume(false);
}
} finally { } finally {
fIndex.flush(); fIndex.flush();
} }
@ -617,12 +619,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
synchronized (this) { synchronized (this) {
fTaskCompleted = true; fTaskCompleted = true;
} }
fProgressMonitor = null;
} }
} }
private void setResume(boolean value) throws InterruptedException, CoreException { private void setResume(boolean value, IProgressMonitor monitor) throws InterruptedException, CoreException {
fIndex.acquireWriteLock(fProgressMonitor); fIndex.acquireWriteLock(monitor);
try { try {
fIndex.getWritableFragment().setProperty(IIndexFragment.PROPERTY_RESUME_INDEXER, String.valueOf(value)); fIndex.getWritableFragment().setProperty(IIndexFragment.PROPERTY_RESUME_INDEXER, String.valueOf(value));
} finally { } finally {
@ -640,10 +641,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
int count= 0; int count= 0;
int forceFirst= fForceNumberFiles; int forceFirst= fForceNumberFiles;
BitSet linkages= new BitSet(); BitSet linkages= new BitSet();
SubMonitor progress = SubMonitor.convert(monitor, fFilesToUpdate.length);
for (final Object tu : fFilesToUpdate) { for (final Object tu : fFilesToUpdate) {
if (monitor.isCanceled()) progress.split(1);
return;
final boolean force= forceAll || --forceFirst >= 0; final boolean force= forceAll || --forceFirst >= 0;
final IIndexFileLocation ifl= fResolver.resolveFile(tu); final IIndexFileLocation ifl= fResolver.resolveFile(tu);
if (ifl == null) if (ifl == null)
@ -828,12 +828,12 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
private void removeFilesInIndex(List<Object> filesToRemove, List<IIndexFragmentFile> indexFilesToRemove, private void removeFilesInIndex(List<Object> filesToRemove, List<IIndexFragmentFile> indexFilesToRemove,
IProgressMonitor monitor) throws InterruptedException, CoreException { IProgressMonitor monitor) throws InterruptedException, CoreException {
if (!filesToRemove.isEmpty() || !indexFilesToRemove.isEmpty()) { if (!filesToRemove.isEmpty() || !indexFilesToRemove.isEmpty()) {
fIndex.acquireWriteLock(fProgressMonitor); SubMonitor progress =
SubMonitor.convert(monitor, 1 + filesToRemove.size() + indexFilesToRemove.size());
fIndex.acquireWriteLock(progress.split(1));
try { try {
for (Object tu : filesToRemove) { for (Object tu : filesToRemove) {
if (monitor.isCanceled()) { progress.split(1);
return;
}
IIndexFileLocation ifl= fResolver.resolveFile(tu); IIndexFileLocation ifl= fResolver.resolveFile(tu);
if (ifl == null) if (ifl == null)
continue; continue;
@ -844,9 +844,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
incrementRequestedFilesCount(-1); incrementRequestedFilesCount(-1);
} }
for (IIndexFragmentFile ifile : indexFilesToRemove) { for (IIndexFragmentFile ifile : indexFilesToRemove) {
if (monitor.isCanceled()) { progress.split(1);
return;
}
fIndex.clearFile(ifile); fIndex.clearFile(ifile);
incrementRequestedFilesCount(-1); incrementRequestedFilesCount(-1);
} }
@ -863,6 +861,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (map == null || files == null || files.isEmpty()) if (map == null || files == null || files.isEmpty())
return; return;
SubMonitor progress = SubMonitor.convert(monitor, files.size() + 1);
int maxPriority = Integer.MIN_VALUE; int maxPriority = Integer.MIN_VALUE;
int minPriority = Integer.MAX_VALUE; int minPriority = Integer.MAX_VALUE;
Map<Integer, List<IIndexFileLocation>> filesByPriority = new HashMap<>(); Map<Integer, List<IIndexFileLocation>> filesByPriority = new HashMap<>();
@ -893,11 +892,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (locTask == null || locTask.isCompleted()) { if (locTask == null || locTask.isCompleted()) {
it.remove(); it.remove();
} else if (locTask.fKind == UpdateKind.REQUIRED_SOURCE) { } else if (locTask.fKind == UpdateKind.REQUIRED_SOURCE) {
if (monitor.isCanceled() || hasUrgentTasks()) if (hasUrgentTasks())
return; return;
final Object tu = locTask.fTu; final Object tu = locTask.fTu;
final IScannerInfo scannerInfo = getScannerInfo(linkageID, tu); 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 { } else {
for (FileVersionTask versionTask : locTask.fVersionTasks) { for (FileVersionTask versionTask : locTask.fVersionTasks) {
if (versionTask.fOutdated) { if (versionTask.fOutdated) {
if (monitor.isCanceled() || hasUrgentTasks()) if (hasUrgentTasks())
return; return;
parseVersionInContext(linkageID, map, ifl, versionTask, locTask.fTu, parseVersionInContext(linkageID, map, ifl, versionTask, locTask.fTu,
new LinkedHashSet<IIndexFile>(), monitor); new LinkedHashSet<IIndexFile>(), progress.split(1));
} }
} }
} }
@ -927,11 +926,11 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
it.remove(); it.remove();
} else { } else {
if (locTask.needsVersion()) { if (locTask.needsVersion()) {
if (monitor.isCanceled() || hasUrgentTasks()) if (hasUrgentTasks())
return; return;
final Object tu = locTask.fTu; final Object tu = locTask.fTu;
final IScannerInfo scannerInfo= getScannerInfo(linkageID, tu); 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()) if (locTask.isCompleted())
it.remove(); it.remove();
@ -940,13 +939,14 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
} }
// Delete remaining files. // Delete remaining files.
fIndex.acquireWriteLock(fProgressMonitor); fIndex.acquireWriteLock(progress.split(1));
try { try {
for (IIndexFileLocation ifl : filesAtPriority) { for (IIndexFileLocation ifl : filesAtPriority) {
LocationTask locTask = map.find(ifl); LocationTask locTask = map.find(ifl);
if (locTask != null && !locTask.isCompleted()) { if (locTask != null && !locTask.isCompleted()) {
if (!locTask.needsVersion()) { if (!locTask.needsVersion()) {
if (monitor.isCanceled() || hasUrgentTasks()) progress.split(1);
if (hasUrgentTasks())
return; return;
Iterator<FileVersionTask> it= locTask.fVersionTasks.iterator(); Iterator<FileVersionTask> it= locTask.fVersionTasks.iterator();
while (it.hasNext()) { while (it.hasNext()) {
@ -973,10 +973,12 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
IProgressMonitor monitor) throws CoreException, InterruptedException { IProgressMonitor monitor) throws CoreException, InterruptedException {
final IIndexFragmentFile headerFile = versionTask.fIndexFile; final IIndexFragmentFile headerFile = versionTask.fIndexFile;
SubMonitor progress = SubMonitor.convert(monitor, 10);
final int safeguardSize= safeGuard.size(); final int safeguardSize= safeGuard.size();
while (true) { while (true) {
progress.setWorkRemaining(10);
// Look for a context and parse the file. // 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) if (ctxFile == null || ctxFile == headerFile)
return; return;
@ -990,23 +992,25 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
Set<IIndexFile> dependencies= null; Set<IIndexFile> dependencies= null;
boolean done= false; boolean done= false;
while (!done) { while (!done) {
progress.setWorkRemaining(9);
done= true; 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) { if (d != null) {
// File was not parsed, because there is a dependency that needs to be // File was not parsed, because there is a dependency that needs to be handled before.
// handled before.
if (dependencies == null) if (dependencies == null)
dependencies= new HashSet<>(); dependencies= new HashSet<>();
if (dependencies.add(d.fIndexFile)) { 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; done= false;
}
} }
} }
} }
if (!ctx.fLostPragmaOnceSemantics) if (!ctx.fLostPragmaOnceSemantics)
return; return;
// Try the next context // Try the next context.
restoreSet(safeGuard, safeguardSize); restoreSet(safeGuard, safeguardSize);
} }
} }
@ -1057,9 +1061,10 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
// Handle the context first. // Handle the context first.
parseVersionInContext(linkageID, map, ctxIfl, ctxVersionTask, ctxTask.fTu, parseVersionInContext(linkageID, map, ctxIfl, ctxVersionTask, ctxTask.fTu,
safeGuard, monitor); safeGuard, monitor);
if (ctxVersionTask.fOutdated // This is unexpected. if (ctxVersionTask.fOutdated // This is unexpected.
|| !versionTask.fOutdated) // Our file was parsed. || !versionTask.fOutdated) { // Our file was parsed.
return null; return null;
}
// The file is no longer a context, look for a different one. // The file is no longer a context, look for a different one.
nextCtx= ctxFile; nextCtx= ctxFile;
@ -1070,8 +1075,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
} }
private DependsOnOutdatedFileException parseFile(Object tu, AbstractLanguage lang, 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 { throws CoreException, InterruptedException {
SubMonitor progress = SubMonitor.convert(monitor, 21);
boolean resultCacheCleared = false; boolean resultCacheCleared = false;
IPath path= getLabel(ifl); IPath path= getLabel(ifl);
Throwable th= null; Throwable th= null;
@ -1079,14 +1085,15 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (fShowActivity) { if (fShowActivity) {
trace("Indexer: parsing " + path.toOSString()); //$NON-NLS-1$ trace("Indexer: parsing " + path.toOSString()); //$NON-NLS-1$
} }
pm.subTask(getMessage(MessageKind.parsingFileTask, progress.subTask(getMessage(MessageKind.parsingFileTask,
path.lastSegment(), path.removeLastSegments(1).toString())); path.lastSegment(), path.removeLastSegments(1).toString()));
FileContent codeReader= fResolver.getCodeReader(tu); FileContent codeReader= fResolver.getCodeReader(tu);
final boolean isSource = fResolver.isSourceUnit(tu); final boolean isSource = fResolver.isSourceUnit(tu);
long start= System.currentTimeMillis(); long start= System.currentTimeMillis();
ASTTypeUtil.startTranslationUnit(); 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; fStatistics.fParsingTime += System.currentTimeMillis() - start;
if (ast == null) { if (ast == null) {
++fStatistics.fTooManyTokensCount; ++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 // Give the new AST a chance to recognize its translation unit before it is written
// to the index. // to the index.
((ASTTranslationUnit) ast).setOriginatingTranslationUnit((ITranslationUnit) tu); ((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. resultCacheCleared = true; // The cache was cleared while writing to the index.
} }
} catch (OperationCanceledException e) {
} catch (RuntimeException e) { } catch (RuntimeException e) {
final Throwable cause = e.getCause(); final Throwable cause = e.getCause();
if (cause instanceof DependsOnOutdatedFileException) if (cause instanceof DependsOnOutdatedFileException)
@ -1118,7 +1126,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
if (!resultCacheCleared) { if (!resultCacheCleared) {
// If the result cache has not been cleared, clear it under a write lock to reduce // If the result cache has not been cleared, clear it under a write lock to reduce
// interference with index readers. // interference with index readers.
fIndex.acquireWriteLock(fProgressMonitor); fIndex.acquireWriteLock(progress.split(1));
try { try {
fIndex.clearResultCache(); fIndex.clearResultCache();
} finally { } finally {
@ -1197,7 +1205,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
private final IASTTranslationUnit createAST(AbstractLanguage language, FileContent codeReader, private final IASTTranslationUnit createAST(AbstractLanguage language, FileContent codeReader,
IScannerInfo scanInfo, boolean isSource, int options, IScannerInfo scanInfo, boolean isSource, int options,
FileContext ctx, IProgressMonitor pm) throws CoreException { FileContext ctx, IProgressMonitor monitor) throws CoreException {
if (codeReader == null) { if (codeReader == null) {
return null; return null;
} }
@ -1233,8 +1241,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
IASTTranslationUnit ast= language.getASTTranslationUnit(codeReader, scanInfo, fCodeReaderFactory, IASTTranslationUnit ast= language.getASTTranslationUnit(codeReader, scanInfo, fCodeReaderFactory,
fIndex, options, getLogService()); fIndex, options, getLogService());
if (pm.isCanceled()) { if (monitor.isCanceled()) {
return null; throw new OperationCanceledException();
} }
return ast; return ast;
} }
@ -1248,7 +1256,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
} }
private void writeToIndex(final int linkageID, IASTTranslationUnit ast, FileContent codeReader, 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<FileContentKey> enteredFiles= new HashSet<>(); HashSet<FileContentKey> enteredFiles= new HashSet<>();
ArrayList<FileInAST> orderedFileKeys= new ArrayList<>(); ArrayList<FileInAST> orderedFileKeys= new ArrayList<>();
@ -1279,9 +1288,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
int storageLinkageID = process(ast, data); int storageLinkageID = process(ast, data);
if (storageLinkageID != ILinkage.NO_LINKAGE_ID) { if (storageLinkageID != ILinkage.NO_LINKAGE_ID) {
IASTComment[] comments = ast.getComments(); 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. // Update task markers.
if (fTodoTaskUpdater != null) { if (fTodoTaskUpdater != null) {
@ -1294,11 +1303,13 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
} }
// Contributed processors now have an opportunity to examine the AST. // Contributed processors now have an opportunity to examine the AST.
for (IPDOMASTProcessor processor : PDOMASTProcessorManager.getProcessors(ast)) { List<IPDOMASTProcessor> processors = PDOMASTProcessorManager.getProcessors(ast);
progress.setWorkRemaining(processors.size());
for (IPDOMASTProcessor processor : processors) {
data = new PDOMWriter.Data(ast, fileKeys, fIndex); data = new PDOMWriter.Data(ast, fileKeys, fIndex);
storageLinkageID = processor.process(ast, data); storageLinkageID = processor.process(ast, data);
if (storageLinkageID != ILinkage.NO_LINKAGE_ID) if (storageLinkageID != ILinkage.NO_LINKAGE_ID)
addSymbols(data, storageLinkageID, ctx, pm); addSymbols(data, storageLinkageID, ctx, progress.split(1));
} }
} catch (CoreException | RuntimeException | Error e) { } catch (CoreException | RuntimeException | Error e) {
// Avoid parsing files again, that caused an exception to be thrown. // 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, private void collectOrderedFileKeys(final int linkageID, IASTInclusionNode inclusion,
HashSet<FileContentKey> enteredFiles, ArrayList<FileInAST> orderedFileKeys) throws CoreException { Set<FileContentKey> enteredFiles, List<FileInAST> orderedFileKeys) throws CoreException {
final IASTPreprocessorIncludeStatement include= inclusion.getIncludeDirective(); final IASTPreprocessorIncludeStatement include= inclusion.getIncludeDirective();
if (include.createsAST()) { if (include.createsAST()) {
final IIndexFileLocation ifl= fResolver.resolveASTPath(include.getPath()); final IIndexFileLocation ifl= fResolver.resolveASTPath(include.getPath());
@ -1352,7 +1363,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
* *
* @return replacement headers keyed by file paths * @return replacement headers keyed by file paths
*/ */
private Map<String, String> extractReplacementHeaders(IASTComment[] comments, IProgressMonitor pm) { private Map<String, String> extractReplacementHeaders(IASTComment[] comments, IProgressMonitor monitor) {
Map<String, String> replacementHeaders = new HashMap<>(); Map<String, String> replacementHeaders = new HashMap<>();
StringBuilder text = new StringBuilder(); StringBuilder text = new StringBuilder();
IASTFileLocation carryoverLocation = null; IASTFileLocation carryoverLocation = null;
@ -1405,8 +1416,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
// include "header" // include "header"
if (text.charAt(matcher.end()) == ',' && if (text.charAt(matcher.end()) == ',' &&
isWhitespace(text, matcher.end() + 1, text.length())) { isWhitespace(text, matcher.end() + 1, text.length())) {
// Defer processing until the next comment, which will be appended to this // Defer processing until the next comment, which will be appended to this one.
// one.
carryoverLocation = location; carryoverLocation = location;
} }
} }
@ -1442,7 +1452,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
return fc; 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); LinkageTask map = findRequestMap(linkageID);
if (map != null) { if (map != null) {
LocationTask locTask= map.find(ifl); LocationTask locTask= map.find(ifl);

View file

@ -58,10 +58,14 @@ public class PDOMIndexerJob extends Job {
@Override @Override
protected void canceling() { protected void canceling() {
// Speed up cancellation by notifying the waiting thread. // Speed up cancellation by notifying the waiting thread.
synchronized(this) { synchronized (this) {
fCancelled= true; fCancelled= true;
notify(); notify();
} }
synchronized (taskMutex) {
if (currentTask != null)
currentTask.cancel();
}
} }
} }
@ -159,15 +163,7 @@ public class PDOMIndexerJob extends Job {
} }
} while (currentTask != null); } while (currentTask != null);
return Status.OK_STATUS; return Status.OK_STATUS;
} catch (RuntimeException e) { } catch (RuntimeException | Error e) {
CCorePlugin.log(e);
pdomManager.cancelledIndexerJob(true);
synchronized (taskMutex) {
currentTask= null;
taskMutex.notifyAll();
}
throw e;
} catch (Error e) {
CCorePlugin.log(e); CCorePlugin.log(e);
pdomManager.cancelledIndexerJob(true); pdomManager.cancelledIndexerJob(true);
synchronized (taskMutex) { synchronized (taskMutex) {

View file

@ -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.parser.scanner.LocationMap;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMASTAdapter; import org.eclipse.cdt.internal.core.pdom.dom.PDOMASTAdapter;
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerASTVisitor; 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.CoreException;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.osgi.util.NLS; import org.eclipse.osgi.util.NLS;
/** /**
@ -203,6 +207,7 @@ public abstract class PDOMWriter implements IPDOMASTProcessor {
protected boolean fShowActivity; protected boolean fShowActivity;
protected final IndexerStatistics fStatistics; protected final IndexerStatistics fStatistics;
protected final IndexerInputAdapter fResolver; protected final IndexerInputAdapter fResolver;
protected final ICanceler fCancelState = new Canceler();
private int fSkipReferences= SKIP_NO_REFERENCES; private int fSkipReferences= SKIP_NO_REFERENCES;
@ -256,7 +261,7 @@ public abstract class PDOMWriter implements IPDOMASTProcessor {
* the index after your last write operation. * the index after your last write operation.
*/ */
final protected void addSymbols(Data data, int storageLinkageID, FileContext ctx, 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) if (data.isEmpty() || storageLinkageID == ILinkage.NO_LINKAGE_ID)
return; return;
@ -266,11 +271,12 @@ public abstract class PDOMWriter implements IPDOMASTProcessor {
fShowSyntaxProblems= true; fShowSyntaxProblems= true;
} }
SubMonitor progress = SubMonitor.convert(monitor, 2);
// Name resolution. // Name resolution.
resolveNames(data, pm); resolveNames(data, progress.split(1));
// Index update. // Index update.
storeSymbolsInIndex(data, storageLinkageID, ctx, pm); storeSymbolsInIndex(data, storageLinkageID, ctx, progress.split(1));
if (!data.fStatuses.isEmpty()) { if (!data.fStatuses.isEmpty()) {
List<IStatus> statuses = data.fStatuses; List<IStatus> 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) private void storeSymbolsInIndex(final Data data, int storageLinkageID, FileContext ctx,
throws InterruptedException, CoreException { IProgressMonitor monitor) throws InterruptedException, CoreException {
final IIndexFragmentFile newFile= ctx == null ? null : ctx.fNewFile; 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++) { for (int i= 0; i < data.fSelectedFiles.length; i++) {
if (pm.isCanceled())
return;
final FileInAST fileInAST= data.fSelectedFiles[i]; final FileInAST fileInAST= data.fSelectedFiles[i];
if (fileInAST != null) { if (fileInAST != null) {
if (fShowActivity) { if (fShowActivity) {
trace("Indexer: adding " + fileInAST.fileContentKey.getLocation().getURI()); //$NON-NLS-1$ trace("Indexer: adding " + fileInAST.fileContentKey.getLocation().getURI()); //$NON-NLS-1$
} }
Throwable th= null; Throwable th= null;
YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, false, pm); YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, false, progress.split(1));
lock.acquire(); lock.acquire();
try { try {
final boolean isReplacement= ctx != null && fileInAST.includeStatement == null; final boolean isReplacement= ctx != null && fileInAST.includeStatement == null;
IIndexFragmentFile ifile= null; IIndexFragmentFile ifile= null;
if (!isReplacement || newFile == null) { if (!isReplacement || newFile == null) {
ifile= storeFileInIndex(data, fileInAST, storageLinkageID, lock); ifile= storeFileInIndex(data, fileInAST, storageLinkageID, lock, progress.split(9));
reportFileWrittenToIndex(fileInAST, ifile); reportFileWrittenToIndex(fileInAST, ifile);
} }
@ -321,8 +325,7 @@ public abstract class PDOMWriter implements IPDOMASTProcessor {
if (ifile == null) if (ifile == null)
ifile= newFile; ifile= newFile;
if (ctx != null && !ctx.fOldFile.equals(ifile) && ifile != null) { if (ctx != null && !ctx.fOldFile.equals(ifile) && ifile != null) {
if (ctx.fOldFile.hasPragmaOnceSemantics() && if (ctx.fOldFile.hasPragmaOnceSemantics() && !ifile.hasPragmaOnceSemantics()) {
!ifile.hasPragmaOnceSemantics()) {
data.fIndex.transferContext(ctx.fOldFile, ifile); data.fIndex.transferContext(ctx.fOldFile, ifile);
ctx.fLostPragmaOnceSemantics= true; ctx.fLostPragmaOnceSemantics= true;
} else { } else {
@ -330,16 +333,11 @@ public abstract class PDOMWriter implements IPDOMASTProcessor {
} }
} }
} }
} catch (RuntimeException e) { } catch (RuntimeException | StackOverflowError | AssertionError e) {
th= e;
} catch (StackOverflowError e) {
th= e;
} catch (AssertionError e) {
th= e; th= e;
} finally { } finally {
// Because the caller holds a read-lock, the result cache of the index is never // Because the caller holds a read-lock, the result cache of the index is never cleared.
// cleared. Before releasing the lock for the last time in this AST, we clear // Before releasing the lock for the last time in this AST, we clear the result cache.
// the result cache.
if (i == data.fSelectedFiles.length - 1) { if (i == data.fSelectedFiles.length - 1) {
data.fIndex.clearResultCache(); 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(); long start= System.currentTimeMillis();
SubMonitor progress = SubMonitor.convert(monitor, data.fSelectedFiles.length);
for (FileInAST file : data.fSelectedFiles) { for (FileInAST file : data.fSelectedFiles) {
if (pm.isCanceled()) {
return;
}
Symbols symbols= data.fSymbolMap.get(file.includeStatement); Symbols symbols= data.fSymbolMap.get(file.includeStatement);
final ArrayList<IASTName[]> names= symbols.fNames; final ArrayList<IASTName[]> names= symbols.fNames;
SubMonitor progress2 = SubMonitor.convert(progress, names.size());
boolean reported= false; boolean reported= false;
for (Iterator<IASTName[]> j = names.iterator(); j.hasNext();) { for (Iterator<IASTName[]> j = names.iterator(); j.hasNext();) {
final IASTName[] na= j.next(); final IASTName[] na= j.next();
final IASTName name = na[0]; final IASTName name = na[0];
progress2.split(1);
if (name != null) { // should not be null, just be defensive. if (name != null) { // should not be null, just be defensive.
Throwable th= null; Throwable th= null;
try { try {
@ -467,8 +465,12 @@ public abstract class PDOMWriter implements IPDOMASTProcessor {
// Names. // Names.
final IndexerASTVisitor visitor = new IndexerASTVisitor((fSkipReferences & SKIP_IMPLICIT_REFERENCES) == 0) { final IndexerASTVisitor visitor = new IndexerASTVisitor((fSkipReferences & SKIP_IMPLICIT_REFERENCES) == 0) {
private int cancelationCheckThrottler;
@Override @Override
public void visit(IASTName name, IASTName caller) { public void visit(IASTName name, IASTName caller) {
checkForCancellation();
if (fSkipReferences == SKIP_ALL_REFERENCES) { if (fSkipReferences == SKIP_ALL_REFERENCES) {
if (name.isReference()) { if (name.isReference()) {
if (!isRequiredReference(name)) { 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); ast.accept(visitor);
@ -558,7 +570,7 @@ public abstract class PDOMWriter implements IPDOMASTProcessor {
} }
private IIndexFragmentFile storeFileInIndex(Data data, FileInAST astFile, int storageLinkageID, 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; final IWritableIndex index = data.fIndex;
IIndexFragmentFile file; IIndexFragmentFile file;
// We create a temporary PDOMFile with zero timestamp, add names to it, then replace // 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) { protected IStatus createStatus(String msg, Throwable e) {
return CCorePlugin.createStatus(msg, e); return CCorePlugin.createStatus(msg, e);
} }
public void cancel() {
fCancelState.setCanceled(true);
}
} }

View file

@ -137,4 +137,10 @@ public class PDOMRebuildTask implements IPDOMIndexerTask {
public synchronized boolean acceptUrgentTask(IPDOMIndexerTask task) { public synchronized boolean acceptUrgentTask(IPDOMIndexerTask task) {
return fDelegate != null && fDelegate.acceptUrgentTask(task); return fDelegate != null && fDelegate.acceptUrgentTask(task);
} }
@Override
public void cancel() {
if (fDelegate != null)
fDelegate.cancel();
}
} }

View file

@ -281,6 +281,12 @@ public class PDOMUpdateTask implements IPDOMIndexerTask {
} }
public void setTranslationUnitSelection(List<? extends ICElement> filesAndFolders) { public void setTranslationUnitSelection(List<? extends ICElement> filesAndFolders) {
fFilesAndFolders= new ArrayList<ICElement>(filesAndFolders); fFilesAndFolders= new ArrayList<>(filesAndFolders);
}
@Override
public void cancel() {
if (fDelegate != null)
fDelegate.cancel();
} }
} }

View file

@ -17,6 +17,7 @@ import org.eclipse.cdt.core.ICLogConstants;
import org.eclipse.cdt.core.parser.AbstractParserLogService; import org.eclipse.cdt.core.parser.AbstractParserLogService;
import org.eclipse.cdt.internal.core.model.DebugLogConstants; import org.eclipse.cdt.internal.core.model.DebugLogConstants;
import org.eclipse.cdt.internal.core.model.Util; 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.ICancelable;
import org.eclipse.cdt.internal.core.util.ICanceler; import org.eclipse.cdt.internal.core.util.ICanceler;
import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Platform;
@ -31,10 +32,12 @@ public class ParserLogService extends AbstractParserLogService implements ICance
private final ICanceler fCanceler; private final ICanceler fCanceler;
public ParserLogService(DebugLogConstants constant) { public ParserLogService(DebugLogConstants constant) {
this(constant, null); this(constant, new Canceler());
} }
public ParserLogService(DebugLogConstants constant, ICanceler canceler) { public ParserLogService(DebugLogConstants constant, ICanceler canceler) {
if (canceler == null)
throw new NullPointerException();
topic = constant; topic = constant;
if (CCorePlugin.getDefault() == null) { if (CCorePlugin.getDefault() == null) {
fIsTracingExceptions= false; fIsTracingExceptions= false;
@ -79,8 +82,16 @@ public class ParserLogService extends AbstractParserLogService implements ICance
@Override @Override
public void setCancelable(ICancelable cancelable) { 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();
} }
} }