DotNext by Roman Sakno

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

 Atomic<T, V, W>

static class Atomic<T, V, W> where W : struct, IAtomicWrapper<T, V>
using System; using System.Runtime.CompilerServices; namespace DotNext.Threading { internal static class Atomic<T, V, W> where W : struct, IAtomicWrapper<T, V> { [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static V CompareExchange(ref W wrapper, ref T value, V update, V expected) { return wrapper.Convert(wrapper.Atomic.CompareExchange(ref value, wrapper.Convert(update), wrapper.Convert(expected))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool CompareAndSet(ref W wrapper, ref T value, V expected, V update) { return wrapper.Atomic.CompareAndSet(ref value, wrapper.Convert(expected), wrapper.Convert(update)); } internal static (V OldValue, V NewValue) Update(ref W wrapper, ref T value, Func<V, V> updater) { V val2; V val; do { val2 = updater(val = wrapper.Convert(wrapper.Atomic.VolatileRead(ref value))); } while (!CompareAndSet(ref wrapper, ref value, val, val2)); return (val, val2); } internal static (V OldValue, V NewValue) Accumulate(ref W wrapper, ref T value, V x, Func<V, V, V> accumulator) { V val2; V val; do { val2 = accumulator(val = wrapper.Convert(wrapper.Atomic.VolatileRead(ref value)), x); } while (!CompareAndSet(ref wrapper, ref value, val, val2)); return (val, val2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static V GetAndSet(ref W wrapper, ref T value, V update) { return wrapper.Convert(wrapper.Atomic.Exchange(ref value, wrapper.Convert(update))); } } }