Ejemplo n.º 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 set.</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 ImmutableSegmentedHashSet <T> location, Func <ImmutableSegmentedHashSet <T>, TArg, ImmutableSegmentedHashSet <T> > transformer, TArg transformerArgument)
        {
            if (transformer is null)
            {
                throw new ArgumentNullException(nameof(transformer));
            }

            var oldValue = ImmutableSegmentedHashSet <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
            }
        }
Ejemplo n.º 2
0
 /// <inheritdoc cref="ImmutableHashSet{T}.Builder.Clear()"/>
 public void Clear()
 {
     if (ReadOnlySet.Count != 0)
     {
         if (_mutableSet is null)
         {
             _mutableSet = new SegmentedHashSet <T>(KeyComparer);
             _set        = default;
         }
         else
         {
             _mutableSet.Clear();
         }
     }
 }
Ejemplo n.º 3
0
        /// <inheritdoc cref="ImmutableHashSet.ToImmutableHashSet{TSource}(ImmutableHashSet{TSource}.Builder)"/>
        public static ImmutableSegmentedHashSet <TSource> ToImmutableSegmentedHashSet <TSource>(this ImmutableSegmentedHashSet <TSource> .Builder builder)
        {
            if (builder is null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            return(builder.ToImmutable());
        }
Ejemplo n.º 4
0
 internal Builder(ImmutableSegmentedHashSet <T> set)
 {
     _set        = set;
     _mutableSet = null;
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Assigns a field or variable containing an immutable set to the specified value if it is has not yet
 /// been initialized.
 /// </summary>
 /// <typeparam name="T">The type of value stored by the set.</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 ImmutableSegmentedHashSet <T> location, ImmutableSegmentedHashSet <T> value)
 {
     return(InterlockedCompareExchange(ref location, value, default(ImmutableSegmentedHashSet <T>)).IsDefault);
 }
Ejemplo n.º 6
0
 /// <summary>
 /// Assigns a field or variable containing an immutable set 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 set.</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 ImmutableSegmentedHashSet <T> InterlockedCompareExchange <T>(ref ImmutableSegmentedHashSet <T> location, ImmutableSegmentedHashSet <T> value, ImmutableSegmentedHashSet <T> comparand)
 {
     return(ImmutableSegmentedHashSet <T> .PrivateInterlocked.InterlockedCompareExchange(ref location, value, comparand));
 }
Ejemplo n.º 7
0
 /// <summary>
 /// Assigns a field or variable containing an immutable set to the specified value and returns the
 /// previous value.
 /// </summary>
 /// <typeparam name="T">The type of value stored by the set.</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 ImmutableSegmentedHashSet <T> InterlockedExchange <T>(ref ImmutableSegmentedHashSet <T> location, ImmutableSegmentedHashSet <T> value)
 {
     return(ImmutableSegmentedHashSet <T> .PrivateInterlocked.InterlockedExchange(ref location, value));
 }