Interlocked.CompareExchange with enum

前端 未结 5 1749
北海茫月
北海茫月 2020-12-31 05:15

I\'m trying to use Interlocked.CompareExchange with this enum:

public enum State {
    Idle,
    Running,
    //...
}

The following code do

5条回答
  •  情书的邮戳
    2020-12-31 05:32

    Using System.Runtime.CompilerServices.Unsafe

    Here's a pretty good related answer going into depth.

    using System;
    using System.Runtime.CompilerServices;
    using System.Threading;
    
    public static class InterlockedEx
    {
        /// 
        /// Enum equivalent of  and 
        /// 
        public static TEnum CompareExchange(ref TEnum location, TEnum value, TEnum comparand)
            where TEnum : struct, Enum
        {
            return Unsafe.SizeOf() switch
            {
                // .NET does not support 1- and 2-byte atomic operations as there
                // is no common hardware support for that.
                4 => CompareExchange32Bit(ref location, value, comparand),
                8 => CompareExchange64Bit(ref location, value, comparand),
                _ => throw new NotSupportedException("Only enums with an underlying type of 4 bytes or 8 bytes are allowed to be used with Interlocked")
            };
    
            static TEnum CompareExchange32Bit(ref TEnum location, TEnum value, TEnum comparand)
            {
                int comparandRaw = Unsafe.As(ref comparand);
                int valueRaw = Unsafe.As(ref value);
                ref int locationRaw = ref Unsafe.As(ref location);
                int returnRaw = Interlocked.CompareExchange(ref locationRaw, valueRaw, comparandRaw);
                return Unsafe.As(ref returnRaw);
            }
    
            static TEnum CompareExchange64Bit(ref TEnum location, TEnum value, TEnum comparand)
            {
                long comparandRaw = Unsafe.As(ref comparand);
                long valueRaw = Unsafe.As(ref value);
                ref long locationRaw = ref Unsafe.As(ref location);
                long returnRaw = Interlocked.CompareExchange(ref locationRaw, valueRaw, comparandRaw);
                return Unsafe.As(ref returnRaw);
            }
        }
    }
    

提交回复
热议问题