DotNext by .NET Foundation and Contributors

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

 Atomic<T>

public struct Atomic<T> : IStrongBox, ICloneable where T : struct
Provides atomic access to non-primitive data type.
using DotNext.Runtime; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext.Threading { [StructLayout(LayoutKind.Auto)] public struct Atomic<T> : IStrongBox, ICloneable where T : struct { private interface IEqualityComparer { bool Equals([In] [IsReadOnly] T x, [In] [IsReadOnly] T y); } [StructLayout(LayoutKind.Auto)] private readonly struct BitwiseEqualityComparer : IEqualityComparer { bool IEqualityComparer.Equals([In] [IsReadOnly] T x, [In] [IsReadOnly] T y) { return EqualityComparer<T>.Default.Equals(x, y); } } [StructLayout(LayoutKind.Auto)] private readonly struct DelegatingEqualityComparer : IEqualityComparer { private readonly Func<T, T, bool> func; internal DelegatingEqualityComparer(Func<T, T, bool> func) { if (func == null) throw new ArgumentNullException("func"); this.func = func; } bool IEqualityComparer.Equals([In] [IsReadOnly] T x, [In] [IsReadOnly] T y) { return func(x, y); } } [StructLayout(LayoutKind.Auto)] private readonly struct EqualityComparer : IEqualityComparer { private readonly IntPtr ptr; internal unsafe EqualityComparer(IntPtr ptr) { if (ptr == (IntPtr)(void*)null) throw new ArgumentNullException("ptr"); this.ptr = ptr; } bool IEqualityComparer.Equals([In] [IsReadOnly] T x, [In] [IsReadOnly] T y) { IntPtr intPtr = ptr; return (byte) != 0; } } public delegate void Updater (ref T current); public delegate void Accumulator (ref T current, [In] [IsReadOnly] T x); private T value; private Atomic.Boolean lockState; public T Value { get { Read(out T result); return result; } set { Write(ref value); } } [Nullable(2)] object IStrongBox.Value { get { return Value; } set { Value = (T)value; } } public Atomic<T> Clone() { Atomic<T> result = default(Atomic<T>); Read(out result.value); return result; } object ICloneable.Clone() { return Clone(); } public void Read(out T result) { lockState.Acquire(); Intrinsics.Copy<T>(ref value, out result); lockState.Release(); } public void Swap(ref Atomic<T> other) { lockState.Acquire(); other.Swap(ref value); lockState.Release(); } public void Swap(ref T other) { lockState.Acquire(); Intrinsics.Swap<T>(ref value, ref other); lockState.Release(); } public void Write([In] [IsReadOnly] ref T newValue) { lockState.Acquire(); Intrinsics.Copy<T>(ref newValue, out value); lockState.Release(); } [MethodImpl(MethodImplOptions.AggressiveOptimization)] private bool CompareExchange<TComparer>(TComparer comparer, [In] [IsReadOnly] ref T update, [In] [IsReadOnly] ref T expected, out T result) where TComparer : struct, IEqualityComparer { this.lockState.Acquire(); T x = this.value; bool num = ((IEqualityComparer)comparer).Equals(ref x, ref expected); if (num) Intrinsics.Copy<T>(ref update, out this.value); Intrinsics.Copy<T>(ref x, out result); this.lockState.Release(); return num; } public bool CompareExchange([In] [IsReadOnly] ref T update, [In] [IsReadOnly] ref T expected, out T result) { return CompareExchange(default(BitwiseEqualityComparer), ref update, ref expected, out result); } public bool CompareExchange([Nullable(new byte[] { 1, 0, 0 })] Func<T, T, bool> comparer, [In] [IsReadOnly] ref T update, [In] [IsReadOnly] ref T expected, out T result) { return CompareExchange(new DelegatingEqualityComparer(comparer), ref update, ref expected, out result); } [CLSCompliant(false)] public bool CompareExchange(IntPtr comparer, [In] [IsReadOnly] ref T update, [In] [IsReadOnly] ref T expected, out T result) { return CompareExchange(new EqualityComparer(comparer), ref update, ref expected, out result); } [MethodImpl(MethodImplOptions.AggressiveOptimization)] private bool CompareAndSet<TComparer>(TComparer comparer, [In] [IsReadOnly] ref T expected, [In] [IsReadOnly] ref T update) where TComparer : struct, IEqualityComparer { this.lockState.Acquire(); try { bool result; if (!(result = ((IEqualityComparer)comparer).Equals(ref this.value, ref expected))) return result; Intrinsics.Copy<T>(ref update, out this.value); return result; } finally { this.lockState.Release(); } } public bool CompareAndSet([In] [IsReadOnly] ref T expected, [In] [IsReadOnly] ref T update) { return CompareAndSet(default(BitwiseEqualityComparer), ref expected, ref update); } public bool CompareAndSet([Nullable(new byte[] { 1, 0, 0 })] Func<T, T, bool> comparer, [In] [IsReadOnly] ref T expected, [In] [IsReadOnly] ref T update) { return CompareAndSet(new DelegatingEqualityComparer(comparer), ref expected, ref update); } [CLSCompliant(false)] public bool CompareAndSet(IntPtr comparer, [In] [IsReadOnly] ref T expected, [In] [IsReadOnly] ref T update) { return CompareAndSet(new EqualityComparer(comparer), ref expected, ref update); } public void Exchange([In] [IsReadOnly] ref T update, out T previous) { lockState.Acquire(); Intrinsics.Copy<T>(ref value, out previous); Intrinsics.Copy<T>(ref update, out value); lockState.Release(); } [MethodImpl(MethodImplOptions.AggressiveOptimization)] public void UpdateAndGet([Nullable(new byte[] { 1, 0 })] Updater updater, out T result) { ArgumentNullException.ThrowIfNull((object)updater, "updater"); lockState.Acquire(); try { updater(ref value); Intrinsics.Copy<T>(ref value, out result); } finally { lockState.Release(); } } [MethodImpl(MethodImplOptions.AggressiveOptimization)] public void GetAndUpdate([Nullable(new byte[] { 1, 0 })] Updater updater, out T result) { ArgumentNullException.ThrowIfNull((object)updater, "updater"); lockState.Acquire(); T input = value; try { updater(ref value); } finally { lockState.Release(); } Intrinsics.Copy<T>(ref input, out result); } [MethodImpl(MethodImplOptions.AggressiveOptimization)] public void AccumulateAndGet([In] [IsReadOnly] ref T x, [Nullable(new byte[] { 1, 0 })] Accumulator accumulator, out T result) { ArgumentNullException.ThrowIfNull((object)accumulator, "accumulator"); lockState.Acquire(); try { accumulator(ref value, ref x); Intrinsics.Copy<T>(ref value, out result); } finally { lockState.Release(); } } [MethodImpl(MethodImplOptions.AggressiveOptimization)] public void GetAndAccumulate([In] [IsReadOnly] ref T x, [Nullable(new byte[] { 1, 0 })] Accumulator accumulator, out T result) { ArgumentNullException.ThrowIfNull((object)accumulator, "accumulator"); lockState.Acquire(); T input = value; try { accumulator(ref value, ref x); } finally { lockState.Release(); } Intrinsics.Copy<T>(ref input, out result); } [NullableContext(2)] public override string ToString() { Read(out T result); return result.ToString(); } } }