Improve Exts.GetOrAdd method to avoid multiple lookups.

Use CollectionsMarshal to hold a ref to the dictionary entry. When the value needs to be added this allows us to set the value directly into it without having to locate the entry a second time.
This commit is contained in:
RoosterDragon
2023-07-07 19:43:59 +01:00
committed by Matthias Mailänder
parent d6a31bb0cc
commit 4a02e6c6cc

View File

@@ -109,13 +109,23 @@ namespace OpenRA
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, V v)
{
#if NET5_0_OR_GREATER
// SAFETY: Dictionary cannot be modified whilst the ref is alive.
ref var value = ref System.Runtime.InteropServices.CollectionsMarshal.GetValueRefOrAddDefault(d, k, out var exists);
if (!exists)
value = v;
return value;
#else
if (!d.TryGetValue(k, out var ret))
d.Add(k, ret = v);
return ret;
#endif
}
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, Func<K, V> createFn)
{
// Cannot use CollectionsMarshal.GetValueRefOrAddDefault here,
// the creation function could mutate the dictionary which would invalidate the ref.
if (!d.TryGetValue(k, out var ret))
d.Add(k, ret = createFn(k));
return ret;