DotNext by Roman Sakno

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

 AtomicEnum<TEnum>

public struct AtomicEnum<TEnum> : IEquatable<TEnum>, ISerializable where TEnum : struct, Enum
Represents atomic enum value.
using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Threading; namespace DotNext.Threading { [Serializable] public struct AtomicEnum<TEnum> : IEquatable<TEnum>, ISerializable where TEnum : struct, Enum { [System.Runtime.CompilerServices.Nullable(1)] private const string ValueSerData = "value"; private long value; public TEnum Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] [IsReadOnly] get { return EnumConverter.ToEnum<TEnum>(ref Unsafe.AsRef<long>(ref value).VolatileRead()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] set { ref this.value.VolatileWrite(EnumConverter.ToInt64<TEnum>(value)); } } public AtomicEnum(TEnum value) { this.value = EnumConverter.ToInt64<TEnum>(value); } [System.Runtime.CompilerServices.NullableContext(1)] private AtomicEnum(SerializationInfo info, StreamingContext context) { value = (long)info.GetValue("value", typeof(long)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public TEnum CompareExchange(TEnum update, TEnum expected) { return EnumConverter.ToEnum<TEnum>(Interlocked.CompareExchange(ref value, EnumConverter.ToInt64<TEnum>(update), EnumConverter.ToInt64<TEnum>(expected))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool CompareAndSet(TEnum expected, TEnum update) { return EqualityComparer<TEnum>.Default.Equals(CompareExchange(update, expected), expected); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public TEnum GetAndSet(TEnum update) { return EnumConverter.ToEnum<TEnum>(ref value.GetAndSet(EnumConverter.ToInt64<TEnum>(update))); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public TEnum SetAndGet(TEnum update) { Value = update; return update; } private (TEnum OldValue, TEnum NewValue) Update([In] [IsReadOnly] ref ValueFunc<TEnum, TEnum> updater) { TEnum val2; TEnum val; do { val2 = updater.Invoke(val = EnumConverter.ToEnum<TEnum>(Volatile.Read(ref value))); } while (!CompareAndSet(val, val2)); return (val, val2); } private (TEnum OldValue, TEnum NewValue) Accumulate(TEnum x, [In] [IsReadOnly] ref ValueFunc<TEnum, TEnum, TEnum> accumulator) { TEnum val2; TEnum val; do { val2 = accumulator.Invoke(val = EnumConverter.ToEnum<TEnum>(Volatile.Read(ref value)), x); } while (!CompareAndSet(val, val2)); return (val, val2); } public TEnum AccumulateAndGet(TEnum x, [System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 0, 0 })] Func<TEnum, TEnum, TEnum> accumulator) { ValueFunc<TEnum, TEnum, TEnum> accumulator2 = new ValueFunc<TEnum, TEnum, TEnum>(accumulator, true); return AccumulateAndGet(x, ref accumulator2); } public TEnum AccumulateAndGet(TEnum x, [In] [IsReadOnly] ref ValueFunc<TEnum, TEnum, TEnum> accumulator) { return Accumulate(x, ref accumulator).NewValue; } public TEnum GetAndAccumulate(TEnum x, [System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 0, 0 })] Func<TEnum, TEnum, TEnum> accumulator) { ValueFunc<TEnum, TEnum, TEnum> accumulator2 = new ValueFunc<TEnum, TEnum, TEnum>(accumulator, true); return GetAndAccumulate(x, ref accumulator2); } public TEnum GetAndAccumulate(TEnum x, [In] [IsReadOnly] ref ValueFunc<TEnum, TEnum, TEnum> accumulator) { return Accumulate(x, ref accumulator).OldValue; } public TEnum UpdateAndGet([System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 0 })] Func<TEnum, TEnum> updater) { ValueFunc<TEnum, TEnum> updater2 = new ValueFunc<TEnum, TEnum>(updater, true); return UpdateAndGet(ref updater2); } public TEnum UpdateAndGet([In] [IsReadOnly] ref ValueFunc<TEnum, TEnum> updater) { return Update(ref updater).NewValue; } public TEnum GetAndUpdate([System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 0 })] Func<TEnum, TEnum> updater) { ValueFunc<TEnum, TEnum> updater2 = new ValueFunc<TEnum, TEnum>(updater, true); return GetAndUpdate(ref updater2); } public TEnum GetAndUpdate([In] [IsReadOnly] ref ValueFunc<TEnum, TEnum> updater) { return Update(ref updater).OldValue; } [IsReadOnly] public bool Equals(TEnum other) { return ref Unsafe.AsRef<long>(ref value).VolatileRead() == EnumConverter.ToInt64<TEnum>(other); } [IsReadOnly] [System.Runtime.CompilerServices.NullableContext(2)] public override bool Equals(object other) { if (!(other is TEnum)) { if (!(other is AtomicEnum<TEnum>)) return false; AtomicEnum<TEnum> atomicEnum = (AtomicEnum<TEnum>)other; return ref atomicEnum.value.VolatileRead() == ref Unsafe.AsRef<long>(ref value).VolatileRead(); } TEnum other2 = (TEnum)other; return Equals(other2); } [IsReadOnly] public override int GetHashCode() { return ref Unsafe.AsRef<long>(ref value).VolatileRead().GetHashCode(); } [IsReadOnly] [System.Runtime.CompilerServices.NullableContext(1)] public override string ToString() { return Value.ToString(); } [IsReadOnly] [System.Runtime.CompilerServices.NullableContext(1)] void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("value", value); } } }