mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 292851 - Made RefactoringASTCache thread-safe.
This commit is contained in:
parent
63b1a31bb5
commit
9e671a6111
1 changed files with 39 additions and 24 deletions
|
@ -10,8 +10,8 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.refactoring;
|
package org.eclipse.cdt.internal.ui.refactoring;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.Assert;
|
import org.eclipse.core.runtime.Assert;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
@ -38,21 +38,26 @@ import org.eclipse.cdt.internal.ui.editor.ASTProvider;
|
||||||
* Cache containing ASTs for the translation units participating in refactoring.
|
* Cache containing ASTs for the translation units participating in refactoring.
|
||||||
* The cache object has to be disposed of after use. Failure to do so may cause
|
* The cache object has to be disposed of after use. Failure to do so may cause
|
||||||
* loss of index lock.
|
* loss of index lock.
|
||||||
|
*
|
||||||
|
* This class is thread-safe.
|
||||||
*/
|
*/
|
||||||
public class RefactoringASTCache implements IDisposable {
|
public class RefactoringASTCache implements IDisposable {
|
||||||
|
private final Map<ITranslationUnit, IASTTranslationUnit> fASTCache;
|
||||||
|
private final Object astBuildMutex;
|
||||||
private IIndex fIndex;
|
private IIndex fIndex;
|
||||||
private Map<ITranslationUnit, IASTTranslationUnit> fASTCache;
|
|
||||||
private boolean fDisposed;
|
private boolean fDisposed;
|
||||||
|
|
||||||
public RefactoringASTCache() {
|
public RefactoringASTCache() {
|
||||||
fASTCache = new HashMap<ITranslationUnit, IASTTranslationUnit>();
|
fASTCache = new ConcurrentHashMap<ITranslationUnit, IASTTranslationUnit>();
|
||||||
|
astBuildMutex = new Object();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an AST for the given translation unit. The AST is built for the working
|
* Returns an AST for the given translation unit. The AST is built for the working
|
||||||
* copy of the translation unit if such working copy exists. The returned AST is a shared
|
* copy of the translation unit if such working copy exists. The returned AST is
|
||||||
* one whenever possible.
|
* a shared one whenever possible.
|
||||||
* NOTE: No references to the AST or its nodes can be kept after calling the {@link #dispose()} method.
|
* NOTE: No references to the AST or its nodes can be kept after calling
|
||||||
|
* the {@link #dispose()} method.
|
||||||
* @param tu The translation unit.
|
* @param tu The translation unit.
|
||||||
* @param pm A progress monitor.
|
* @param pm A progress monitor.
|
||||||
* @return An AST, or <code>null</code> if the AST cannot be obtained.
|
* @return An AST, or <code>null</code> if the AST cannot be obtained.
|
||||||
|
@ -60,20 +65,12 @@ public class RefactoringASTCache implements IDisposable {
|
||||||
public IASTTranslationUnit getAST(ITranslationUnit tu, IProgressMonitor pm)
|
public IASTTranslationUnit getAST(ITranslationUnit tu, IProgressMonitor pm)
|
||||||
throws CoreException, OperationCanceledException {
|
throws CoreException, OperationCanceledException {
|
||||||
Assert.isTrue(!fDisposed, "RefactoringASTCache is already disposed"); //$NON-NLS-1$
|
Assert.isTrue(!fDisposed, "RefactoringASTCache is already disposed"); //$NON-NLS-1$
|
||||||
if (fIndex == null) {
|
getIndex(); // Make sure the index is locked.
|
||||||
ICProject[] projects;
|
|
||||||
projects = CoreModel.getDefault().getCModel().getCProjects();
|
|
||||||
IIndex index = CCorePlugin.getIndexManager().getIndex(projects);
|
|
||||||
try {
|
|
||||||
index.acquireReadLock();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new OperationCanceledException();
|
|
||||||
}
|
|
||||||
fIndex = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
tu= CModelUtil.toWorkingCopy(tu);
|
tu= CModelUtil.toWorkingCopy(tu);
|
||||||
IASTTranslationUnit ast= fASTCache.get(tu);
|
IASTTranslationUnit ast;
|
||||||
|
ast= fASTCache.get(tu);
|
||||||
|
|
||||||
if (ast == null) {
|
if (ast == null) {
|
||||||
// Try to get a shared AST before creating our own.
|
// Try to get a shared AST before creating our own.
|
||||||
final IASTTranslationUnit[] astHolder = new IASTTranslationUnit[1];
|
final IASTTranslationUnit[] astHolder = new IASTTranslationUnit[1];
|
||||||
|
@ -86,6 +83,10 @@ public class RefactoringASTCache implements IDisposable {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ast = astHolder[0];
|
ast = astHolder[0];
|
||||||
|
|
||||||
|
if (ast == null) {
|
||||||
|
synchronized (astBuildMutex) {
|
||||||
|
ast= fASTCache.get(tu);
|
||||||
if (ast == null) {
|
if (ast == null) {
|
||||||
int options= ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT |
|
int options= ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT |
|
||||||
ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
|
ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
|
||||||
|
@ -93,6 +94,8 @@ public class RefactoringASTCache implements IDisposable {
|
||||||
fASTCache.put(tu, ast);
|
fASTCache.put(tu, ast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (pm != null) {
|
if (pm != null) {
|
||||||
pm.done();
|
pm.done();
|
||||||
}
|
}
|
||||||
|
@ -104,13 +107,25 @@ public class RefactoringASTCache implements IDisposable {
|
||||||
*
|
*
|
||||||
* @return The index.
|
* @return The index.
|
||||||
*/
|
*/
|
||||||
public IIndex getIndex() {
|
public synchronized IIndex getIndex() throws CoreException, OperationCanceledException {
|
||||||
Assert.isTrue(!fDisposed, "RefactoringASTCache is already disposed"); //$NON-NLS-1$
|
Assert.isTrue(!fDisposed, "RefactoringASTCache is already disposed"); //$NON-NLS-1$
|
||||||
|
if (fIndex == null) {
|
||||||
|
ICProject[] projects;
|
||||||
|
projects = CoreModel.getDefault().getCModel().getCProjects();
|
||||||
|
IIndex index = CCorePlugin.getIndexManager().getIndex(projects);
|
||||||
|
try {
|
||||||
|
index.acquireReadLock();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
}
|
||||||
|
fIndex = index;
|
||||||
|
}
|
||||||
return fIndex;
|
return fIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see IDisposable#dispose()
|
* @see IDisposable#dispose()
|
||||||
|
* This method should not be called concurrently with any other method.
|
||||||
*/
|
*/
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
Assert.isTrue(!fDisposed, "RefactoringASTCache.dispose() called more than once"); //$NON-NLS-1$
|
Assert.isTrue(!fDisposed, "RefactoringASTCache.dispose() called more than once"); //$NON-NLS-1$
|
||||||
|
|
Loading…
Add table
Reference in a new issue