/// <summary> /// Adds value to hash tree /// </summary> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TValue"></typeparam> /// <param name="destination"></param> /// <param name="key">key to add</param> /// <param name="value">value being added</param> /// <param name="updateIfExists">if true update, if false just leave existing</param> /// <returns>final value for key</returns> public static TValue ThreadSafeAdd <TKey, TValue>(ref ImmutableHashTree <TKey, TValue> destination, TKey key, TValue value, bool updateIfExists = false) { var returnValue = value; ThreadSafeAdd(ref destination, key, value, (currentValue, newValue) => { if (updateIfExists) { return(newValue); } returnValue = currentValue; return(currentValue); }); return(returnValue); }
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; if (ReferenceEquals(currentValue, Interlocked.CompareExchange(ref destination, currentValue.Add(key, value, updateDelegate), currentValue))) { return; } SpinWaitThreadSafeAddS(ref destination, key, value, updateDelegate); }