Atomic<T>
Provides atomic access to non-primitive data type.
using DotNext.Runtime;
using System;
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 BitwiseComparer<T>.Equals(ref x, ref 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 AtomicBoolean lockState;
public T Value {
[IsReadOnly]
get {
Read(out T result);
return result;
}
set {
Write(ref value);
}
}
[System.Runtime.CompilerServices.Nullable(2)]
object IStrongBox.Value {
[IsReadOnly]
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();
}
[IsReadOnly]
public void Read(out T result)
{
AtomicBoolean atomicBoolean = lockState;
atomicBoolean.Acquire();
Intrinsics.Copy<T>(ref value, out result);
atomicBoolean = lockState;
atomicBoolean.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([System.Runtime.CompilerServices.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();
bool num = ((IEqualityComparer)comparer).Equals(ref this.value, ref expected);
if (num)
Intrinsics.Copy<T>(ref update, out this.value);
this.lockState.Release();
return num;
}
public bool CompareAndSet([In] [IsReadOnly] ref T expected, [In] [IsReadOnly] ref T update)
{
return CompareAndSet(default(BitwiseEqualityComparer), ref expected, ref update);
}
public bool CompareAndSet([System.Runtime.CompilerServices.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([System.Runtime.CompilerServices.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([System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0
})] Updater updater, out T result)
{
ArgumentNullException.ThrowIfNull((object)updater, "updater");
lockState.Acquire();
T input = value;
try {
updater(ref value);
Intrinsics.Copy<T>(ref input, out result);
} finally {
lockState.Release();
}
}
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public void AccumulateAndGet([In] [IsReadOnly] ref T x, [System.Runtime.CompilerServices.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, [System.Runtime.CompilerServices.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);
Intrinsics.Copy<T>(ref input, out result);
} finally {
lockState.Release();
}
}
[IsReadOnly]
[System.Runtime.CompilerServices.NullableContext(2)]
public override string ToString()
{
Read(out T result);
return result.ToString();
}
}
}