Пример #1
0
        /// <summary>
        /// Mutates a value in-place with optimistic locking transaction semantics via a specified transformation
        /// function. The transformation is retried as many times as necessary to win the optimistic locking race.
        /// </summary>
        /// <typeparam name="T">The type of value stored by the list.</typeparam>
        /// <typeparam name="TArg">The type of argument passed to the <paramref name="transformer"/>.</typeparam>
        /// <param name="location">
        /// The variable or field to be changed, which may be accessed by multiple threads.
        /// </param>
        /// <param name="transformer">
        /// A function that mutates the value. This function should be side-effect free, as it may run multiple times
        /// when races occur with other threads.</param>
        /// <param name="transformerArgument">The argument to pass to <paramref name="transformer"/>.</param>
        /// <returns>
        /// <see langword="true"/> if the location's value is changed by applying the result of the
        /// <paramref name="transformer"/> function; otherwise, <see langword="false"/> if the location's value remained
        /// the same because the last invocation of <paramref name="transformer"/> returned the existing value.
        /// </returns>
        public static bool Update <T, TArg>(ref ImmutableSegmentedList <T> location, Func <ImmutableSegmentedList <T>, TArg, ImmutableSegmentedList <T> > transformer, TArg transformerArgument)
        {
            if (transformer is null)
            {
                throw new ArgumentNullException(nameof(transformer));
            }

            var oldValue = ImmutableSegmentedList <T> .PrivateInterlocked.VolatileRead(in location);

            while (true)
            {
                var newValue = transformer(oldValue, transformerArgument);
                if (oldValue == newValue)
                {
                    // No change was actually required.
                    return(false);
                }

                var interlockedResult = InterlockedCompareExchange(ref location, newValue, oldValue);
                if (oldValue == interlockedResult)
                {
                    return(true);
                }

                oldValue = interlockedResult; // we already have a volatile read that we can reuse for the next loop
            }
        }
        /// <inheritdoc cref="ImmutableList.ToImmutableList{TSource}(ImmutableList{TSource}.Builder)"/>
        public static ImmutableSegmentedList <T> ToImmutableSegmentedList <T>(this ImmutableSegmentedList <T> .Builder builder)
        {
            if (builder is null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            return(builder.ToImmutable());
        }
Пример #3
0
 /// <summary>
 /// Assigns a field or variable containing an immutable list to the specified value if it is has not yet been
 /// initialized.
 /// </summary>
 /// <typeparam name="T">The type of value stored by the list.</typeparam>
 /// <param name="location">The field or local variable to change.</param>
 /// <param name="value">The new value to assign.</param>
 /// <returns><see langword="true"/> if the field was assigned the specified value; otherwise,
 /// <see langword="false"/> if it was previously initialized.</returns>
 public static bool InterlockedInitialize <T>(ref ImmutableSegmentedList <T> location, ImmutableSegmentedList <T> value)
 {
     return(InterlockedCompareExchange(ref location, value, default(ImmutableSegmentedList <T>)).IsDefault);
 }
Пример #4
0
 /// <summary>
 /// Assigns a field or variable containing an immutable list to the specified value if it is currently equal to
 /// another specified value. Returns the previous value.
 /// </summary>
 /// <typeparam name="T">The type of value stored by the list.</typeparam>
 /// <param name="location">The field or local variable to change.</param>
 /// <param name="value">The new value to assign.</param>
 /// <param name="comparand">The value to check equality for before assigning.</param>
 /// <returns>The prior value at the specified <paramref name="location"/>.</returns>
 public static ImmutableSegmentedList <T> InterlockedCompareExchange <T>(ref ImmutableSegmentedList <T> location, ImmutableSegmentedList <T> value, ImmutableSegmentedList <T> comparand)
 {
     return(ImmutableSegmentedList <T> .PrivateInterlocked.InterlockedCompareExchange(ref location, value, comparand));
 }
Пример #5
0
 /// <summary>
 /// Assigns a field or variable containing an immutable list to the specified value and returns the previous
 /// value.
 /// </summary>
 /// <typeparam name="T">The type of value stored by the list.</typeparam>
 /// <param name="location">The field or local variable to change.</param>
 /// <param name="value">The new value to assign.</param>
 /// <returns>The prior value at the specified <paramref name="location"/>.</returns>
 public static ImmutableSegmentedList <T> InterlockedExchange <T>(ref ImmutableSegmentedList <T> location, ImmutableSegmentedList <T> value)
 {
     return(ImmutableSegmentedList <T> .PrivateInterlocked.InterlockedExchange(ref location, value));
 }
Пример #6
0
 internal Builder(ImmutableSegmentedList <T> list)
 => _builder = new ValueBuilder(list);
 internal ValueBuilder(ImmutableSegmentedList <T> list)
 {
     _list        = list;
     _mutableList = null;
 }