AtomicIntPtr
Various atomic operations for IntPtr data type
accessible as extension methods.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
namespace DotNext.Threading
{
public static class AtomicIntPtr
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr VolatileRead([In] [IsReadOnly] ref IntPtr value)
{
return Volatile.Read(ref Unsafe.AsRef(ref value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void VolatileWrite(ref IntPtr value, IntPtr newValue)
{
Volatile.Write(ref value, newValue);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr IncrementAndGet(ref IntPtr value)
{
switch (IntPtr.Size) {
case 4:
return (IntPtr)Interlocked.Increment(ref Unsafe.As<IntPtr, int>(ref value));
case 8:
return (IntPtr)Interlocked.Increment(ref Unsafe.As<IntPtr, long>(ref value));
default:
return Update(ref value, default(Increment)).NewValue;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr DecrementAndGet(ref IntPtr value)
{
switch (IntPtr.Size) {
case 4:
return (IntPtr)Interlocked.Decrement(ref Unsafe.As<IntPtr, int>(ref value));
case 8:
return (IntPtr)Interlocked.Decrement(ref Unsafe.As<IntPtr, long>(ref value));
default:
return Update(ref value, default(Decrement)).NewValue;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr AddAndGet(ref IntPtr value, IntPtr operand)
{
switch (IntPtr.Size) {
case 4:
return (IntPtr)Interlocked.Add(ref Unsafe.As<IntPtr, int>(ref value), (int)operand);
case 8:
return (IntPtr)Interlocked.Add(ref Unsafe.As<IntPtr, long>(ref value), (long)operand);
default:
return Accumulate(ref value, operand, default(Adder)).NewValue;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr GetAndAdd(ref IntPtr value, IntPtr operand)
{
return Accumulate(ref value, operand, default(Adder)).OldValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr GetAndBitwiseAnd(ref IntPtr value, IntPtr operand)
{
switch (IntPtr.Size) {
case 4:
return (IntPtr)Interlocked.And(ref Unsafe.As<IntPtr, int>(ref value), (int)operand);
case 8:
return (IntPtr)Interlocked.And(ref Unsafe.As<IntPtr, long>(ref value), (long)operand);
default:
return Accumulate(ref value, operand, default(BitwiseAnd)).OldValue;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static IntPtr BitwiseAndAndGet(ref IntPtr value, IntPtr operand)
{
switch (IntPtr.Size) {
case 4:
return (IntPtr)(void*)((long)Interlocked.And(ref Unsafe.As<IntPtr, int>(ref value), (int)operand) & (long)operand);
case 8:
return (IntPtr)(void*)((long)(IntPtr)(void*)Interlocked.And(ref Unsafe.As<IntPtr, long>(ref value), (long)operand) & (long)operand);
default:
return Accumulate(ref value, operand, default(BitwiseAnd)).NewValue;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr GetAndBitwiseOr(ref IntPtr value, IntPtr operand)
{
switch (IntPtr.Size) {
case 4:
return (IntPtr)Interlocked.Or(ref Unsafe.As<IntPtr, int>(ref value), (int)operand);
case 8:
return (IntPtr)Interlocked.Or(ref Unsafe.As<IntPtr, long>(ref value), (long)operand);
default:
return Accumulate(ref value, operand, default(BitwiseAnd)).OldValue;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static IntPtr BitwiseOrAndGet(ref IntPtr value, IntPtr operand)
{
switch (IntPtr.Size) {
case 4:
return (IntPtr)(void*)((long)Interlocked.Or(ref Unsafe.As<IntPtr, int>(ref value), (int)operand) | (long)operand);
case 8:
return (IntPtr)(void*)((long)(IntPtr)(void*)Interlocked.Or(ref Unsafe.As<IntPtr, long>(ref value), (long)operand) | (long)operand);
default:
return Accumulate(ref value, operand, default(BitwiseOr)).NewValue;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr GetAndBitwiseXor(ref IntPtr value, IntPtr operand)
{
return Accumulate(ref value, operand, default(BitwiseXor)).OldValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr BitwiseXorAndGet(ref IntPtr value, IntPtr operand)
{
return Accumulate(ref value, operand, default(BitwiseXor)).NewValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool CompareAndSet(ref IntPtr value, IntPtr expected, IntPtr update)
{
return Interlocked.CompareExchange(ref value, update, expected) == expected;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr GetAndSet(ref IntPtr value, IntPtr update)
{
return Interlocked.Exchange(ref value, update);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr SetAndGet(ref IntPtr value, IntPtr update)
{
ref value.VolatileWrite(update);
return update;
}
private static (IntPtr OldValue, IntPtr NewValue) Update<TUpdater>(ref IntPtr value, TUpdater updater) where TUpdater : struct, ISupplier<IntPtr, IntPtr>
{
IntPtr intPtr = Volatile.Read(ref value);
IntPtr intPtr3;
IntPtr intPtr2;
do {
intPtr3 = ((ISupplier<IntPtr, IntPtr>)updater).Invoke(intPtr2 = intPtr);
} while ((intPtr = Interlocked.CompareExchange(ref value, intPtr3, intPtr2)) != intPtr2);
return (intPtr2, intPtr3);
}
private static (IntPtr OldValue, IntPtr NewValue) Accumulate<TAccumulator>(ref IntPtr value, IntPtr x, TAccumulator accumulator) where TAccumulator : struct, ISupplier<IntPtr, IntPtr, IntPtr>
{
IntPtr intPtr = Volatile.Read(ref value);
IntPtr intPtr3;
IntPtr intPtr2;
do {
intPtr3 = ((ISupplier<IntPtr, IntPtr, IntPtr>)accumulator).Invoke(intPtr2 = intPtr, x);
} while ((intPtr = Interlocked.CompareExchange(ref value, intPtr3, intPtr2)) != intPtr2);
return (intPtr2, intPtr3);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[System.Runtime.CompilerServices.NullableContext(1)]
public static IntPtr AccumulateAndGet(ref IntPtr value, IntPtr x, Func<IntPtr, IntPtr, IntPtr> accumulator)
{
return Accumulate(ref value, x, (DelegatingSupplier<IntPtr, IntPtr, IntPtr>)accumulator).NewValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[CLSCompliant(false)]
public static IntPtr AccumulateAndGet(ref IntPtr value, IntPtr x, IntPtr accumulator)
{
return Accumulate(ref value, x, (Supplier<IntPtr, IntPtr, IntPtr>)(long)accumulator).NewValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[System.Runtime.CompilerServices.NullableContext(1)]
public static IntPtr GetAndAccumulate(ref IntPtr value, IntPtr x, Func<IntPtr, IntPtr, IntPtr> accumulator)
{
return Accumulate(ref value, x, (DelegatingSupplier<IntPtr, IntPtr, IntPtr>)accumulator).OldValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[CLSCompliant(false)]
public static IntPtr GetAndAccumulate(ref IntPtr value, IntPtr x, IntPtr accumulator)
{
return Accumulate(ref value, x, (Supplier<IntPtr, IntPtr, IntPtr>)(long)accumulator).OldValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[System.Runtime.CompilerServices.NullableContext(1)]
public static IntPtr UpdateAndGet(ref IntPtr value, Func<IntPtr, IntPtr> updater)
{
return Update(ref value, (DelegatingSupplier<IntPtr, IntPtr>)updater).NewValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[CLSCompliant(false)]
public static IntPtr UpdateAndGet(ref IntPtr value, IntPtr updater)
{
return Update(ref value, (Supplier<IntPtr, IntPtr>)(long)updater).NewValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[System.Runtime.CompilerServices.NullableContext(1)]
public static IntPtr GetAndUpdate(ref IntPtr value, Func<IntPtr, IntPtr> updater)
{
return Update(ref value, (DelegatingSupplier<IntPtr, IntPtr>)updater).OldValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[CLSCompliant(false)]
public static IntPtr GetAndUpdate(ref IntPtr value, IntPtr updater)
{
return Update(ref value, (Supplier<IntPtr, IntPtr>)(long)updater).OldValue;
}
}
}