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:
committed by
Matthias Mailänder
parent
d6a31bb0cc
commit
4a02e6c6cc
@@ -109,13 +109,23 @@ namespace OpenRA
|
|||||||
|
|
||||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, V v)
|
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))
|
if (!d.TryGetValue(k, out var ret))
|
||||||
d.Add(k, ret = v);
|
d.Add(k, ret = v);
|
||||||
return ret;
|
return ret;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, Func<K, V> createFn)
|
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))
|
if (!d.TryGetValue(k, out var ret))
|
||||||
d.Add(k, ret = createFn(k));
|
d.Add(k, ret = createFn(k));
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user