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;
}
}
}