AtomicReference<T>
Provides container with atomic operations
for the reference type.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Threading;
namespace DotNext.Threading
{
[Serializable]
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public struct AtomicReference<[System.Runtime.CompilerServices.Nullable(2)] T> : IEquatable<T>, ISerializable where T : class
{
private const string ValueSerData = "Value";
private T value;
public T Value {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[IsReadOnly]
[return: MaybeNull]
get {
return Volatile.Read<T>(ref Unsafe.AsRef<T>(ref value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set {
Volatile.Write<T>(ref this.value, value);
}
}
public AtomicReference(T value)
{
this.value = value;
}
private AtomicReference(SerializationInfo info, StreamingContext context)
{
value = (T)info.GetValue("Value", typeof(T));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T CompareExchange(T expected, T update)
{
return Interlocked.CompareExchange<T>(ref value, update, expected);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool CompareAndSet(T expected, T update)
{
return AtomicReference.CompareAndSet<T>(ref value, expected, update);
}
[IsReadOnly]
public override string ToString()
{
return Value?.ToString() ?? "NULL";
}
[IsReadOnly]
public bool Equals([AllowNull] T other)
{
return object.Equals(other, Value);
}
[IsReadOnly]
[System.Runtime.CompilerServices.NullableContext(2)]
public override bool Equals(object other)
{
if (!(other is AtomicReference<T>))
return object.Equals(other, Value);
return Equals(((AtomicReference<T>)other).Value);
}
[IsReadOnly]
public override int GetHashCode()
{
return Value?.GetHashCode() ?? 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T GetAndSet(T update)
{
return Interlocked.Exchange<T>(ref value, update);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[return: NotNullIfNotNull("update")]
public T SetAndGet(T update)
{
Value = update;
return update;
}
public T AccumulateAndGet(T x, Func<T, T, T> accumulator)
{
return AtomicReference.AccumulateAndGet<T>(ref value, x, accumulator);
}
public T AccumulateAndGet(T x, [In] [IsReadOnly] [System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1,
1,
1
})] ref ValueFunc<T, T, T> accumulator)
{
return AtomicReference.AccumulateAndGet<T>(ref value, x, ref accumulator);
}
public T GetAndAccumulate(T x, Func<T, T, T> accumulator)
{
return AtomicReference.GetAndAccumulate<T>(ref value, x, accumulator);
}
public T GetAndAccumulate(T x, [In] [IsReadOnly] [System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1,
1,
1
})] ref ValueFunc<T, T, T> accumulator)
{
return AtomicReference.GetAndAccumulate<T>(ref value, x, ref accumulator);
}
public T UpdateAndGet(Func<T, T> updater)
{
return AtomicReference.UpdateAndGet<T>(ref value, updater);
}
public T UpdateAndGet([In] [IsReadOnly] [System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1,
1
})] ref ValueFunc<T, T> updater)
{
return AtomicReference.UpdateAndGet<T>(ref value, ref updater);
}
public T GetAndUpdate(Func<T, T> updater)
{
return AtomicReference.GetAndUpdate<T>(ref value, updater);
}
public T GetAndUpdate([In] [IsReadOnly] [System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1,
1
})] ref ValueFunc<T, T> updater)
{
return AtomicReference.GetAndUpdate<T>(ref value, ref updater);
}
[return: NotNull]
public T SetIfNull<TDerived>() where TDerived : T, new
{
T val = this.Value;
if (val == null) {
val = (T)(object)new TDerived();
return this.CompareExchange((T)null, val) ?? val;
}
return val;
}
public T SetIfNull(Func<T> supplier)
{
T val = Value;
if (val == null) {
val = supplier();
return CompareExchange(null, val) ?? val;
}
return val;
}
[IsReadOnly]
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Value", value, typeof(T));
}
}
}