Make model access thread-safe

This commit is contained in:
Katy Coe
2019-12-14 12:00:47 +01:00
parent 934def3f66
commit 8d272a25fc
2 changed files with 14 additions and 7 deletions

View File

@@ -5,6 +5,7 @@
*/
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -26,7 +27,7 @@ namespace Il2CppInspector.Reflection
public TypeInfo[] TypesByUsageIndex { get; }
// List of type usages that are initialized via pointers in the image
public Dictionary<ulong, TypeInfo> TypesByVirtualAddress { get; } = new Dictionary<ulong, TypeInfo>();
public ConcurrentDictionary<ulong, TypeInfo> TypesByVirtualAddress { get; } = new ConcurrentDictionary<ulong, TypeInfo>();
// Every type
public IEnumerable<TypeInfo> Types => new IEnumerable<TypeInfo>[] { TypesByDefinitionIndex, TypesByUsageIndex, TypesByVirtualAddress.Values }.SelectMany(t => t);
@@ -35,7 +36,7 @@ namespace Il2CppInspector.Reflection
public MethodBase[] MethodsByDefinitionIndex { get; }
// List of all generated CustomAttributeData objects by their index into AttributeTypeIndices
public Dictionary<int, CustomAttributeData> AttributesByIndices { get; } = new Dictionary<int, CustomAttributeData>();
public ConcurrentDictionary<int, CustomAttributeData> AttributesByIndices { get; } = new ConcurrentDictionary<int, CustomAttributeData>();
public Il2CppModel(Il2CppInspector package) {
Package = package;
@@ -114,7 +115,7 @@ namespace Il2CppInspector.Reflection
var type = Package.BinaryImage.ReadMappedObject<Il2CppType>(ptr);
var newUsage = getNewTypeUsage(type, MemberTypes.NestedType);
TypesByVirtualAddress.Add(ptr, newUsage);
TypesByVirtualAddress.TryAdd(ptr, newUsage);
return newUsage;
}

View File

@@ -49,14 +49,20 @@ namespace Il2CppInspector.Reflection
attribute = new CustomAttributeData { Index = customAttributeIndex, AttributeType = asm.Model.GetTypeFromUsage(typeIndex) };
asm.Model.AttributesByIndices.Add(i, attribute);
asm.Model.AttributesByIndices.TryAdd(i, attribute);
yield return attribute;
}
}
private static IList<CustomAttributeData> getCustomAttributes(Assembly asm, uint token, int customAttributeIndex)
=> getCustomAttributes(asm, asm.Model.GetCustomAttributeIndex(asm, token, customAttributeIndex)).ToList();
private static readonly object gcaLock = new object();
private static IList<CustomAttributeData> getCustomAttributes(Assembly asm, uint token, int customAttributeIndex) {
// Force the generation of the collection to be thread-safe
// Convert the result into a list for thread-safe enumeration
lock (gcaLock) {
return getCustomAttributes(asm, asm.Model.GetCustomAttributeIndex(asm, token, customAttributeIndex)).ToList();
}
}
public static IList<CustomAttributeData> GetCustomAttributes(Assembly asm) => getCustomAttributes(asm, asm.AssemblyDefinition.token, asm.AssemblyDefinition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(EventInfo evt) => getCustomAttributes(evt.Assembly, evt.Definition.token, evt.Definition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(FieldInfo field) => getCustomAttributes(field.Assembly, field.Definition.token, field.Definition.customAttributeIndex);