Browse Source

Fixed SD2-1510: Too slow startup when DesignerViewContent.cs was open

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3768 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
1a0d6c4cdd
  1. 5
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs
  2. 90
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs
  3. 7
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionClass.cs

5
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs

@ -174,12 +174,15 @@ namespace ICSharpCode.SharpDevelop.Dom
|| type.BaseType.FullName == "System.MulticastDelegate"; || type.BaseType.FullName == "System.MulticastDelegate";
} }
protected override bool KeepInheritanceTree {
get { return true; }
}
public CecilClass(ICompilationUnit compilationUnit, IClass declaringType, public CecilClass(ICompilationUnit compilationUnit, IClass declaringType,
TypeDefinition td, string fullName) TypeDefinition td, string fullName)
: base(compilationUnit, declaringType) : base(compilationUnit, declaringType)
{ {
this.FullyQualifiedName = fullName; this.FullyQualifiedName = fullName;
this.KeepInheritanceTree = true;
AddAttributes(compilationUnit.ProjectContent, this.Attributes, td.CustomAttributes); AddAttributes(compilationUnit.ProjectContent, this.Attributes, td.CustomAttributes);

90
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs

@ -6,8 +6,9 @@
// </file> // </file>
using System; using System;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace ICSharpCode.SharpDevelop.Dom namespace ICSharpCode.SharpDevelop.Dom
{ {
@ -373,17 +374,72 @@ namespace ICSharpCode.SharpDevelop.Dom
return CompareTo((IClass)o); return CompareTo((IClass)o);
} }
volatile List<IClass> inheritanceTreeCache; sealed class InheritanceTreeCache
{
internal IClass[] inheritanceTree;
internal bool isCreating;
}
volatile InheritanceTreeCache inheritanceTreeCache;
public IEnumerable<IClass> ClassInheritanceTree { public IEnumerable<IClass> ClassInheritanceTree {
get { get {
List<IClass> visitedList = inheritanceTreeCache; // Notes:
if (visitedList != null) // the ClassInheritanceTree must work even if the following things happen:
return visitedList; // - cyclic inheritance
visitedList = new List<IClass>(); // - multithreaded calls
// - recursive calls (the SearchType request done by GetUnderlyingClass() uses ClassInheritanceTree)
// Especially the recursive calls are tricky, this has caused incorrect behavior (SD2-1474)
// or performance problems (SD2-1510) in the past.
// get the inheritanceTreeCache, creating it if required
// (on demand-creation saves memory - lots of classes never need a ClassInheritanceTree)
InheritanceTreeCache inheritanceTreeCache = this.inheritanceTreeCache;
if (inheritanceTreeCache == null) {
// but ensure only one is created, even when ClassInheritanceTree is called by multiple threads
InheritanceTreeCache newCache = new InheritanceTreeCache();
#pragma warning disable 420
// Warning CS0420: 'ICSharpCode.SharpDevelop.Dom.DefaultClass.inheritanceTreeCache': a reference to a volatile field will not be treated as volatile
// We disable this warning because Interlocked.* treats the location as volatile, even though
// normally ref-parameters in C# lose the volatile modifier.
inheritanceTreeCache = Interlocked.CompareExchange(ref this.inheritanceTreeCache, newCache, null) ?? newCache;
#pragma warning restore 420
}
// now we have the inheritanceTreeCache -> lock on it
lock (inheritanceTreeCache) {
if (inheritanceTreeCache.inheritanceTree == null) {
// inheritance tree does not exist yet
if (inheritanceTreeCache.isCreating) {
// this is a recursive call -> don't produce inheritance tree
return EmptyList<IClass>.Instance;
} else {
// now produce the actual inheritance tree
inheritanceTreeCache.isCreating = true;
inheritanceTreeCache.inheritanceTree = CalculateClassInheritanceTree();
inheritanceTreeCache.isCreating = false;
if (!KeepInheritanceTree)
DomCache.RegisterForClear(ClearCachedInheritanceTree);
}
}
return inheritanceTreeCache.inheritanceTree;
}
}
}
void ClearCachedInheritanceTree()
{
lock (inheritanceTreeCache) {
inheritanceTreeCache.inheritanceTree = null;
}
}
IClass[] CalculateClassInheritanceTree()
{
List<IClass> visitedList = new List<IClass>();
Queue<IReturnType> typesToVisit = new Queue<IReturnType>(); Queue<IReturnType> typesToVisit = new Queue<IReturnType>();
bool enqueuedLastBaseType = false; bool enqueuedLastBaseType = false;
bool hasErrors = false;
IClass currentClass = this; IClass currentClass = this;
IReturnType nextType; IReturnType nextType;
do { do {
@ -403,29 +459,17 @@ namespace ICSharpCode.SharpDevelop.Dom
} }
if (nextType != null) { if (nextType != null) {
currentClass = nextType.GetUnderlyingClass(); currentClass = nextType.GetUnderlyingClass();
if (currentClass == null)
hasErrors = true;
} }
} while (nextType != null); } while (nextType != null);
return visitedList.ToArray();
// A SearchType request causes the inheritance tree to be generated, but if it was
// this classes' base type that caused the SearchType request, the GetUnderlyingClass()
// will fail and we will produce an incomplete inheritance tree.
// So we don't cache incomplete inheritance trees for parsed classes (fixes SD2-1474).
if (!hasErrors || KeepInheritanceTree) {
inheritanceTreeCache = visitedList;
if (!KeepInheritanceTree)
DomCache.RegisterForClear(delegate { inheritanceTreeCache = null; });
}
return visitedList;
}
} }
/// <summary> /// <summary>
/// Specifies whether to keep the inheritance tree when the DomCache is cleared. /// Specifies whether to keep the inheritance tree when the DomCache is cleared.
/// </summary> /// </summary>
protected bool KeepInheritanceTree = false; protected virtual bool KeepInheritanceTree {
get { return false; }
}
public IReturnType GetBaseType(int index) public IReturnType GetBaseType(int index)
{ {

7
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionClass.cs

@ -105,8 +105,6 @@ namespace ICSharpCode.SharpDevelop.Dom.ReflectionLayer
FullyQualifiedName = fullName; FullyQualifiedName = fullName;
} }
this.KeepInheritanceTree = true;
try { try {
AddAttributes(compilationUnit.ProjectContent, this.Attributes, CustomAttributeData.GetCustomAttributes(type)); AddAttributes(compilationUnit.ProjectContent, this.Attributes, CustomAttributeData.GetCustomAttributes(type));
} catch (Exception ex) { } catch (Exception ex) {
@ -184,6 +182,9 @@ namespace ICSharpCode.SharpDevelop.Dom.ReflectionLayer
} }
} }
} }
}
protected override bool KeepInheritanceTree {
get { return true; }
}
}
} }

Loading…
Cancel
Save