AtomicReference<T>
Provides container with atomic operations
for the reference type.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Threading;
namespace DotNext.Threading
{
[Serializable]
public struct AtomicReference<T> : IEquatable<T>, ISerializable where T : class
{
private const string ValueSerData = "Value";
private T value;
public T Value {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get {
return Volatile.Read<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);
}
public override string ToString()
{
return Value?.ToString() ?? "NULL";
}
public bool Equals(T other)
{
return object.Equals(other, Value);
}
public override bool Equals(object other)
{
if (!(other is AtomicReference<T>))
return Equals(other as T);
return Equals(((AtomicReference<T>)other).Value);
}
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)]
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] [System.Runtime.CompilerServices.IsReadOnly] 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] [System.Runtime.CompilerServices.IsReadOnly] 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] [System.Runtime.CompilerServices.IsReadOnly] 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] [System.Runtime.CompilerServices.IsReadOnly] ref ValueFunc<T, T> updater)
{
return AtomicReference.GetAndUpdate<T>(ref value, ref updater);
}
public T SetIfNull<G>() where G : T, new
{
T val = this.Value;
if (val == null) {
val = (T)(object)new G();
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;
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Value", value, typeof(T));
}
}
}