DotNext by .NET Foundation and Contributors

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

 AtomicIntPtr

public static class 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; } } }