private static void SpinWaitThreadSafeAddS <TKey, TValue>(ref ImmutableHashTree <TKey, TValue> destination, TKey key, TValue value, ImmutableHashTree <TKey, TValue> .UpdateDelegate updateDelegate) { ImmutableHashTree <TKey, TValue> currentValue; var wait = new SpinWait(); while (true) { wait.SpinOnce(); currentValue = destination; if (ReferenceEquals(currentValue, Interlocked.CompareExchange(ref destination, currentValue.Add(key, value, updateDelegate), currentValue))) { break; } } }
/// <summary> /// Add to tree in a thread safe manner /// </summary> /// <typeparam name="TKey">key type</typeparam> /// <typeparam name="TValue">value type</typeparam> /// <param name="destination">hash tree to add to</param> /// <param name="key">key</param> /// <param name="value">value</param> /// <param name="updateDelegate">update delegate</param> public static void ThreadSafeAdd <TKey, TValue>(ref ImmutableHashTree <TKey, TValue> destination, TKey key, TValue value, ImmutableHashTree <TKey, TValue> .UpdateDelegate updateDelegate) { if (destination == null) { throw new ArgumentNullException(nameof(destination)); } if (key == null) { throw new ArgumentNullException(nameof(key)); } var currentValue = destination; var newValue = currentValue.Add(key, value, updateDelegate); if (Interlocked.CompareExchange(ref destination, newValue, currentValue) == currentValue) { return; } var wait = new SpinWait(); while (true) { wait.SpinOnce(); currentValue = destination; newValue = currentValue.Add(key, value, updateDelegate); if (Interlocked.CompareExchange(ref destination, newValue, currentValue) == currentValue) { break; } } }