예제 #1
0
        /// <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);
        }
예제 #2
0
        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;
                }
            }
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        /// <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;
                }
            }
        }