DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="4.12.0" />

 AtomicDouble

public static class AtomicDouble
Various atomic operations for Double data type accessible as extension methods.
using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; namespace DotNext.Threading { public static class AtomicDouble { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double VolatileRead([In] [IsReadOnly] ref double value) { return Volatile.Read(ref Unsafe.AsRef(ref value)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void VolatileWrite(ref double value, double newValue) { Volatile.Write(ref value, newValue); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double IncrementAndGet(ref double value) { return Update(ref value, default(Increment)).NewValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double DecrementAndGet(ref double value) { return Update(ref value, default(Decrement)).NewValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AddAndGet(ref double value, double operand) { return Accumulate(ref value, operand, default(Adder)).NewValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double GetAndAdd(ref double value, double operand) { return Accumulate(ref value, operand, default(Adder)).OldValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool Equals(double x, double y) { if (x != y) { if (double.IsNaN(x)) return double.IsNaN(y); return false; } return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool CompareAndSet(ref double value, double expected, double update) { return Equals(Interlocked.CompareExchange(ref value, update, expected), expected); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double GetAndSet(ref double value, double update) { return Interlocked.Exchange(ref value, update); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double SetAndGet(ref double value, double update) { ref value.VolatileWrite(update); return update; } private static (double OldValue, double NewValue) Update<TUpdater>(ref double value, TUpdater updater) where TUpdater : struct, ISupplier<double, double> { double num = Volatile.Read(ref value); double num3; double num2; do { num3 = ((ISupplier<double, double>)updater).Invoke(num2 = num); } while ((num = Interlocked.CompareExchange(ref value, num3, num2)) != num2); return (num2, num3); } private static (double OldValue, double NewValue) Accumulate<TAccumulator>(ref double value, double x, TAccumulator accumulator) where TAccumulator : struct, ISupplier<double, double, double> { double num = Volatile.Read(ref value); double num3; double num2; do { num3 = ((ISupplier<double, double, double>)accumulator).Invoke(num2 = num, x); } while ((num = Interlocked.CompareExchange(ref value, num3, num2)) != num2); return (num2, num3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.CompilerServices.NullableContext(1)] public static double AccumulateAndGet(ref double value, double x, Func<double, double, double> accumulator) { return Accumulate(ref value, x, (DelegatingSupplier<double, double, double>)accumulator).NewValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static double AccumulateAndGet(ref double value, double x, IntPtr accumulator) { return Accumulate(ref value, x, (Supplier<double, double, double>)(long)accumulator).NewValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.CompilerServices.NullableContext(1)] public static double GetAndAccumulate(ref double value, double x, Func<double, double, double> accumulator) { return Accumulate(ref value, x, (DelegatingSupplier<double, double, double>)accumulator).OldValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static double GetAndAccumulate(ref double value, double x, IntPtr accumulator) { return Accumulate(ref value, x, (Supplier<double, double, double>)(long)accumulator).OldValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.CompilerServices.NullableContext(1)] public static double UpdateAndGet(ref double value, Func<double, double> updater) { return Update(ref value, (DelegatingSupplier<double, double>)updater).NewValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static double UpdateAndGet(ref double value, IntPtr updater) { return Update(ref value, (Supplier<double, double>)(long)updater).NewValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.CompilerServices.NullableContext(1)] public static double GetAndUpdate(ref double value, Func<double, double> updater) { return Update(ref value, (DelegatingSupplier<double, double>)updater).OldValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static double GetAndUpdate(ref double value, IntPtr updater) { return Update(ref value, (Supplier<double, double>)(long)updater).OldValue; } } }