Browse Source

Fixed thread-safety problem in DefaultReturnType.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@4432 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
89c64e389c
  1. 102
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs

102
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs

@ -67,26 +67,33 @@ namespace ICSharpCode.SharpDevelop.Dom
return c; return c;
} }
bool getMembersBusy; // Required to prevent stack overflow when calling GetMethods() on a class with cyclic inheritance
// replaces old 'getMembersBusy' flag which wasn't thread-safe
[ThreadStatic] static BusyManager _busyManager;
static BusyManager busyManager {
get { return _busyManager ?? (_busyManager = new BusyManager()); }
}
public override List<IMethod> GetMethods() public override List<IMethod> GetMethods()
{ {
if (getMembersBusy) return new List<IMethod>();
getMembersBusy = true;
List<IMethod> l = new List<IMethod>(); List<IMethod> l = new List<IMethod>();
l.AddRange(c.Methods); using (var busyLock = busyManager.Enter(this)) {
if (c.ClassType == ClassType.Interface) { if (busyLock.Success) {
if (c.BaseTypes.Count == 0) { l.AddRange(c.Methods);
AddMethodsFromBaseType(l, c.ProjectContent.SystemTypes.Object); if (c.ClassType == ClassType.Interface) {
} else { if (c.BaseTypes.Count == 0) {
foreach (IReturnType baseType in c.BaseTypes) { AddMethodsFromBaseType(l, c.ProjectContent.SystemTypes.Object);
AddMethodsFromBaseType(l, baseType); } else {
foreach (IReturnType baseType in c.BaseTypes) {
AddMethodsFromBaseType(l, baseType);
}
}
} else {
AddMethodsFromBaseType(l, c.BaseType);
} }
} }
} else {
AddMethodsFromBaseType(l, c.BaseType);
} }
getMembersBusy = false;
return l; return l;
} }
@ -120,18 +127,19 @@ namespace ICSharpCode.SharpDevelop.Dom
public override List<IProperty> GetProperties() public override List<IProperty> GetProperties()
{ {
if (getMembersBusy) return new List<IProperty>();
getMembersBusy = true;
List<IProperty> l = new List<IProperty>(); List<IProperty> l = new List<IProperty>();
l.AddRange(c.Properties); using (var busyLock = busyManager.Enter(this)) {
if (c.ClassType == ClassType.Interface) { if (busyLock.Success) {
foreach (IReturnType baseType in c.BaseTypes) { l.AddRange(c.Properties);
AddPropertiesFromBaseType(l, baseType); if (c.ClassType == ClassType.Interface) {
foreach (IReturnType baseType in c.BaseTypes) {
AddPropertiesFromBaseType(l, baseType);
}
} else {
AddPropertiesFromBaseType(l, c.BaseType);
}
} }
} else {
AddPropertiesFromBaseType(l, c.BaseType);
} }
getMembersBusy = false;
return l; return l;
} }
@ -162,41 +170,43 @@ namespace ICSharpCode.SharpDevelop.Dom
public override List<IField> GetFields() public override List<IField> GetFields()
{ {
if (getMembersBusy) return new List<IField>();
getMembersBusy = true;
List<IField> l = new List<IField>(); List<IField> l = new List<IField>();
l.AddRange(c.Fields); using (var busyLock = busyManager.Enter(this)) {
if (c.ClassType == ClassType.Interface) { if (busyLock.Success) {
foreach (IReturnType baseType in c.BaseTypes) { l.AddRange(c.Fields);
l.AddRange(baseType.GetFields()); if (c.ClassType == ClassType.Interface) {
} foreach (IReturnType baseType in c.BaseTypes) {
} else { l.AddRange(baseType.GetFields());
IReturnType baseType = c.BaseType; }
if (baseType != null) { } else {
l.AddRange(baseType.GetFields()); IReturnType baseType = c.BaseType;
if (baseType != null) {
l.AddRange(baseType.GetFields());
}
}
} }
} }
getMembersBusy = false;
return l; return l;
} }
public override List<IEvent> GetEvents() public override List<IEvent> GetEvents()
{ {
if (getMembersBusy) return new List<IEvent>();
getMembersBusy = true;
List<IEvent> l = new List<IEvent>(); List<IEvent> l = new List<IEvent>();
l.AddRange(c.Events); using (var busyLock = busyManager.Enter(this)) {
if (c.ClassType == ClassType.Interface) { if (busyLock.Success) {
foreach (IReturnType baseType in c.BaseTypes) { l.AddRange(c.Events);
l.AddRange(baseType.GetEvents()); if (c.ClassType == ClassType.Interface) {
} foreach (IReturnType baseType in c.BaseTypes) {
} else { l.AddRange(baseType.GetEvents());
IReturnType baseType = c.BaseType; }
if (baseType != null) { } else {
l.AddRange(baseType.GetEvents()); IReturnType baseType = c.BaseType;
if (baseType != null) {
l.AddRange(baseType.GetEvents());
}
}
} }
} }
getMembersBusy = false;
return l; return l;
} }

Loading…
Cancel
Save