/// <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()); }
/// <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); }
/// <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)); }
/// <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)); }
internal Builder(ImmutableSegmentedList <T> list) => _builder = new ValueBuilder(list);
internal ValueBuilder(ImmutableSegmentedList <T> list) { _list = list; _mutableList = null; }