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