File: system\threading\interlocked.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
//
// <OWNER>Microsoft</OWNER>
namespace System.Threading
{
    using System;
    using System.Security.Permissions;
    using System.Runtime.CompilerServices;
    using System.Runtime.ConstrainedExecution;
    using System.Runtime.Versioning;
    using System.Runtime;
 
    // After much discussion, we decided the Interlocked class doesn't need 
    // any HPA's for synchronization or external threading.  They hurt C#'s 
    // codegen for the yield keyword, and arguably they didn't protect much.  
    // Instead, they penalized people (and compilers) for writing threadsafe 
    // code.
    public static class Interlocked
    {        
        /******************************
         * Increment
         *   Implemented: int
         *                        long
         *****************************/
 
        [ResourceExposure(ResourceScope.None)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public static int Increment(ref int location)
        {
            return Add(ref location, 1);
        }
 
        [ResourceExposure(ResourceScope.None)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public static long Increment(ref long location)
        {
            return Add(ref location, 1);
        }
 
        /******************************
         * Decrement
         *   Implemented: int
         *                        long
         *****************************/
 
        [ResourceExposure(ResourceScope.None)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public static int Decrement(ref int location)
        {
            return Add(ref location, -1);
        }
 
        [ResourceExposure(ResourceScope.None)]
        public static long Decrement(ref long location)
        {
            return Add(ref location, -1);
        }
 
        /******************************
         * Exchange
         *   Implemented: int
         *                        long
         *                        float
         *                        double
         *                        Object
         *                        IntPtr
         *****************************/
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        public static extern int Exchange(ref int location1, int value);
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [System.Security.SecuritySafeCritical]
        public static extern long Exchange(ref long location1, long value);
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [System.Security.SecuritySafeCritical]
        public static extern float Exchange(ref float location1, float value);
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [System.Security.SecuritySafeCritical]
        public static extern double Exchange(ref double location1, double value);
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        public static extern Object Exchange(ref Object location1, Object value);
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        public static extern IntPtr Exchange(ref IntPtr location1, IntPtr value);
 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Runtime.InteropServices.ComVisible(false)]
        [System.Security.SecuritySafeCritical]
        public static T Exchange<T>(ref T location1, T value) where T : class
        {
            _Exchange(__makeref(location1), __makeref(value));
            //Since value is a local we use trash its data on return
            //  The Exchange replaces the data with new data
            //  so after the return "value" contains the original location1
            //See ExchangeGeneric for more details           
            return value;
        }
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        private static extern void _Exchange(TypedReference location1, TypedReference value);
 
        /******************************
         * CompareExchange
         *    Implemented: int
         *                         long
         *                         float
         *                         double
         *                         Object
         *                         IntPtr
         *****************************/
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        public static extern int CompareExchange(ref int location1, int value, int comparand);    
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [System.Security.SecuritySafeCritical]
        public static extern long CompareExchange(ref long location1, long value, long comparand);    
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [System.Security.SecuritySafeCritical]
        public static extern float CompareExchange(ref float location1, float value, float comparand);    
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [System.Security.SecuritySafeCritical]
        public static extern double CompareExchange(ref double location1, double value, double comparand);    
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        public static extern Object CompareExchange(ref Object location1, Object value, Object comparand);
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        public static extern IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand);
 
        /*****************************************************************
         * CompareExchange<T>
         * 
         * Notice how CompareExchange<T>() uses the __makeref keyword
         * to create two TypedReferences before calling _CompareExchange().
         * This is horribly slow. Ideally we would like CompareExchange<T>()
         * to simply call CompareExchange(ref Object, Object, Object); 
         * however, this would require casting a "ref T" into a "ref Object", 
         * which is not legal in C#.
         * 
         * Thus we opted to cheat, and hacked to JIT so that when it reads
         * the method body for CompareExchange<T>() it gets back the
         * following IL:
         *
         *     ldarg.0 
         *     ldarg.1
         *     ldarg.2
         *     call System.Threading.Interlocked::CompareExchange(ref Object, Object, Object)
         *     ret
         *
         * See getILIntrinsicImplementationForInterlocked() in VM\JitInterface.cpp
         * for details.
         *****************************************************************/
        
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Runtime.InteropServices.ComVisible(false)]
        [System.Security.SecuritySafeCritical]
        public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class
        {
            // _CompareExchange() passes back the value read from location1 via local named 'value'
            _CompareExchange(__makeref(location1), __makeref(value), comparand);
            return value;
        }
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        private static extern void _CompareExchange(TypedReference location1, TypedReference value, Object comparand);
 
        // BCL-internal overload that returns success via a ref bool param, useful for reliable spin locks.
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        internal static extern int CompareExchange(ref int location1, int value, int comparand, ref bool succeeded);
 
        /******************************
         * Add
         *    Implemented: int
         *                         long
         *****************************/
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        internal static extern int ExchangeAdd(ref int location1, int value);
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern long ExchangeAdd(ref long location1, long value);
 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public static int Add(ref int location1, int value) 
        {
            return ExchangeAdd(ref location1, value) + value;
        }
 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public static long Add(ref long location1, long value) 
        {
            return ExchangeAdd(ref location1, value) + value;
        }
     
        /******************************
         * Read
         *****************************/
        public static long Read(ref long location)
        {
            return Interlocked.CompareExchange(ref location,0,0);
        }
 
 
        public static void MemoryBarrier()
        {
            Thread.MemoryBarrier();
        }
 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [System.Security.SecuritySafeCritical]
        extern public static void SpeculationBarrier();
    }
}