fix: Fix threading issue in EnumUtils cache

This commit is contained in:
Drew Tingen
2020-12-13 16:16:57 -05:00
committed by Chris Cameron
parent f9a8be85d6
commit 9819c44dcc

View File

@@ -15,7 +15,10 @@ namespace ICD.Common.Utils
public static class EnumUtils public static class EnumUtils
{ {
private static readonly Dictionary<Type, object[]> s_EnumValuesCache; private static readonly Dictionary<Type, object[]> s_EnumValuesCache;
private static readonly SafeCriticalSection s_EnumValuesCacheSection;
private static readonly Dictionary<Type, Dictionary<object, object[]>> s_EnumFlagsCache; private static readonly Dictionary<Type, Dictionary<object, object[]>> s_EnumFlagsCache;
private static readonly SafeCriticalSection s_EnumFlagsCacheSection;
/// <summary> /// <summary>
/// Static constructor. /// Static constructor.
@@ -23,7 +26,9 @@ namespace ICD.Common.Utils
static EnumUtils() static EnumUtils()
{ {
s_EnumValuesCache = new Dictionary<Type, object[]>(); s_EnumValuesCache = new Dictionary<Type, object[]>();
s_EnumValuesCacheSection = new SafeCriticalSection();
s_EnumFlagsCache = new Dictionary<Type, Dictionary<object, object[]>>(); s_EnumFlagsCache = new Dictionary<Type, Dictionary<object, object[]>>();
s_EnumFlagsCacheSection = new SafeCriticalSection();
} }
#region Validation #region Validation
@@ -59,6 +64,7 @@ namespace ICD.Common.Utils
/// <returns></returns> /// <returns></returns>
public static bool IsEnum<T>(T value) public static bool IsEnum<T>(T value)
{ {
// ReSharper disable once CompareNonConstrainedGenericWithNull
return value != null && IsEnumType(value.GetType()); return value != null && IsEnumType(value.GetType());
} }
@@ -168,7 +174,7 @@ namespace ICD.Common.Utils
throw new ArgumentNullException("type"); throw new ArgumentNullException("type");
// Reflection is slow and this method is called a lot, so we cache the results. // Reflection is slow and this method is called a lot, so we cache the results.
return s_EnumValuesCache.GetOrAddNew(type, () => GetValuesUncached(type).ToArray()); return s_EnumValuesCacheSection.Execute(() => s_EnumValuesCache.GetOrAddNew(type, () => GetValuesUncached(type).ToArray()));
} }
/// <summary> /// <summary>
@@ -346,10 +352,10 @@ namespace ICD.Common.Utils
/// <returns></returns> /// <returns></returns>
public static IEnumerable<object> GetFlags(Type type, object value) public static IEnumerable<object> GetFlags(Type type, object value)
{ {
return s_EnumFlagsCache.GetOrAddNew(type, () => new Dictionary<object, object[]>()) return s_EnumFlagsCacheSection.Execute(() => s_EnumFlagsCache.GetOrAddNew(type, () => new Dictionary<object, object[]>())
.GetOrAddNew(value, () => GetValues(type) .GetOrAddNew(value, () => GetValues(type)
.Where(f => HasFlag(value, f)) .Where(f => HasFlag(value, f))
.ToArray()); .ToArray()));
} }
/// <summary> /// <summary>