1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Potential deadlock in CElement.getElementInfo()

We can no longer synch on CModelMager.  We need
	to do some fine grained lock for the LRU caching.

	* model/org/eclipse/cdt/internal/core/model/CElement.java
	* model/org/eclipse/cdt/internal/core/model/CModelManager.java
	* model/org/eclipse/cdt/internal/core/model/Openable.java
This commit is contained in:
Alain Magloire 2004-06-04 17:38:44 +00:00
parent 180f029292
commit a9c11b6167
4 changed files with 92 additions and 22 deletions

View file

@ -1,3 +1,13 @@
2004-06-04 Alain Magloire
Potential deadlock in CElement.getElementInfo()
We can no longer synch on CModelMager. We need
to do some fine grained lock for the LRU caching.
* model/org/eclipse/cdt/internal/core/model/CElement.java
* model/org/eclipse/cdt/internal/core/model/CModelManager.java
* model/org/eclipse/cdt/internal/core/model/Openable.java
2004-06-03 Alain Magloire 2004-06-03 Alain Magloire
The Elf class should not depend of GNU The Elf class should not depend of GNU

View file

@ -233,8 +233,7 @@ public abstract class CElement extends PlatformObject implements ICElement {
} }
public CElementInfo getElementInfo () throws CModelException { public CElementInfo getElementInfo () throws CModelException {
CModelManager manager; CModelManager manager = CModelManager.getDefault();
synchronized(manager = CModelManager.getDefault()){
Object info = manager.getInfo(this); Object info = manager.getInfo(this);
if (info == null) { if (info == null) {
openHierarchy(); openHierarchy();
@ -245,7 +244,6 @@ public abstract class CElement extends PlatformObject implements ICElement {
} }
return (CElementInfo)info; return (CElementInfo)info;
} }
}
public String toString() { public String toString() {
return getElementName(); return getElementName();

View file

@ -109,6 +109,11 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe
*/ */
protected Map elementsOutOfSynchWithBuffers = new HashMap(11); protected Map elementsOutOfSynchWithBuffers = new HashMap(11);
/*
* Temporary cache of newly opened elements
*/
private ThreadLocal temporaryCache = new ThreadLocal();
/** /**
* Infos cache. * Infos cache.
*/ */
@ -986,31 +991,73 @@ public class CModelManager implements IResourceChangeListener, ICDescriptorListe
/** /**
* Returns the info for the element. * Returns the info for the element.
*/ */
public Object getInfo(ICElement element) { public synchronized Object getInfo(ICElement element) {
HashMap tempCache = (HashMap)this.temporaryCache.get();
if (tempCache != null) {
Object result = tempCache.get(element);
if (result != null) {
return result;
}
}
return this.cache.getInfo(element); return this.cache.getInfo(element);
} }
/** /**
* Returns the info for this element without * Returns the info for this element without
* disturbing the cache ordering. * disturbing the cache ordering.
*/ */
protected Object peekAtInfo(ICElement element) { protected synchronized Object peekAtInfo(ICElement element) {
HashMap tempCache = (HashMap)this.temporaryCache.get();
if (tempCache != null) {
Object result = tempCache.get(element);
if (result != null) {
return result;
}
}
return this.cache.peekAtInfo(element); return this.cache.peekAtInfo(element);
} }
/** /**
* Puts the info for a C Model Element * Puts the info for a C Model Element
*/ */
protected void putInfo(ICElement element, Object info) { protected synchronized void putInfo(ICElement element, Object info) {
this.cache.putInfo(element, info); this.cache.putInfo(element, info);
} }
/** /**
* Removes the info of this model element. * Removes the info of this model element.
*/ */
protected void removeInfo(ICElement element) { protected synchronized void removeInfo(ICElement element) {
this.cache.removeInfo(element); this.cache.removeInfo(element);
} }
/*
* Returns the temporary cache for newly opened elements for the current thread.
* Creates it if not already created.
*/
public HashMap getTemporaryCache() {
HashMap result = (HashMap)this.temporaryCache.get();
if (result == null) {
result = new HashMap();
this.temporaryCache.set(result);
}
return result;
}
/*
* Returns whether there is a temporary cache for the current thread.
*/
public boolean hasTemporaryCache() {
return this.temporaryCache.get() != null;
}
/*
* Resets the temporary cache for newly created elements to null.
*/
public void resetTemporaryCache() {
this.temporaryCache.set(null);
}
/** /**
* *
*/ */

View file

@ -66,13 +66,12 @@ public abstract class Openable extends Parent implements IOpenable, IBufferChang
* removing the current infos, generating new infos, and then placing * removing the current infos, generating new infos, and then placing
* the new infos into the C Model cache tables. * the new infos into the C Model cache tables.
*/ */
protected void buildStructure(OpenableInfo info, IProgressMonitor monitor) throws CModelException { protected void buildStructure(OpenableInfo info, HashMap newElements, IProgressMonitor monitor) throws CModelException {
if (monitor != null && monitor.isCanceled()) return; if (monitor != null && monitor.isCanceled()) return;
// remove existing (old) infos // remove existing (old) infos
removeInfo(); removeInfo();
HashMap newElements = new HashMap(11);
info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource())); info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource()));
CModelManager.getDefault().getElementsOutOfSynchWithBuffers().remove(this); CModelManager.getDefault().getElementsOutOfSynchWithBuffers().remove(this);
for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) { for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) {
@ -122,9 +121,6 @@ public abstract class Openable extends Parent implements IOpenable, IBufferChang
* the structure of this element. * the structure of this element.
*/ */
protected abstract boolean generateInfos(OpenableInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws CModelException; protected abstract boolean generateInfos(OpenableInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws CModelException;
//protected boolean generateInfos(OpenableInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws CModelException {
// return false;
//}
/** /**
* @see org.eclipse.cdt.core.model.IOpenable#getBuffer() * @see org.eclipse.cdt.core.model.IOpenable#getBuffer()
@ -231,7 +227,16 @@ public abstract class Openable extends Parent implements IOpenable, IBufferChang
public void makeConsistent(IProgressMonitor pm, boolean forced) throws CModelException { public void makeConsistent(IProgressMonitor pm, boolean forced) throws CModelException {
if (!isConsistent() || forced) { if (!isConsistent() || forced) {
buildStructure((OpenableInfo)getElementInfo(), pm); CModelManager manager = CModelManager.getDefault();
boolean hadTemporaryCache = manager.hasTemporaryCache();
try {
HashMap newElements = manager.getTemporaryCache();
buildStructure((OpenableInfo)getElementInfo(), newElements, pm);
} finally {
if (!hadTemporaryCache) {
manager.resetTemporaryCache();
}
}
} }
} }
@ -273,8 +278,10 @@ public abstract class Openable extends Parent implements IOpenable, IBufferChang
* <code>isOpen()</code>). * <code>isOpen()</code>).
*/ */
protected void openWhenClosed(IProgressMonitor pm) throws CModelException { protected void openWhenClosed(IProgressMonitor pm) throws CModelException {
CModelManager manager = CModelManager.getDefault();
boolean hadTemporaryCache = manager.hasTemporaryCache();
try { try {
HashMap newElements = manager.getTemporaryCache();
// 1) Parent must be open - open the parent if necessary // 1) Parent must be open - open the parent if necessary
openParent(pm); openParent(pm);
@ -286,7 +293,11 @@ public abstract class Openable extends Parent implements IOpenable, IBufferChang
} }
// 3) build the structure of the openable // 3) build the structure of the openable
buildStructure(info, pm); buildStructure(info, newElements, pm);
//if (!hadTemporaryCache) {
// manager.putInfos(this, newElements);
//}
// if any problems occuring openning the element, ensure that it's info // if any problems occuring openning the element, ensure that it's info
// does not remain in the cache (some elements, pre-cache their info // does not remain in the cache (some elements, pre-cache their info
@ -294,6 +305,10 @@ public abstract class Openable extends Parent implements IOpenable, IBufferChang
} catch (CModelException e) { } catch (CModelException e) {
CModelManager.getDefault().removeInfo(this); CModelManager.getDefault().removeInfo(this);
throw e; throw e;
} finally {
if (!hadTemporaryCache) {
manager.resetTemporaryCache();
}
} }
} }