The Labs \ Source Viewer \ SSCLI \ System.Runtime.CompilerServices \ ExecuteWithLockHelper

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. ////////////////////////////////////////////////////////////////////////////////
  16. ////////////////////////////////////////////////////////////////////////////////
  17. //
  18. // RuntimeHelpers
  19. // This class defines a set of static methods that provide support for compilers.
  20. //
  21. // Date: April 2000
  22. //
  23. namespace System.Runtime.CompilerServices
  24. {
  25.    
  26.     using System;
  27.     using System.Runtime.CompilerServices;
  28.     using System.Runtime.InteropServices;
  29.     using System.Runtime.ConstrainedExecution;
  30.     using System.Security.Permissions;
  31.     using System.Threading;
  32.    
  33.     public static class RuntimeHelpers
  34.     {
  35.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  36.         public static extern void InitializeArray(Array array, RuntimeFieldHandle fldHandle);
  37.        
  38.         // GetObjectValue is intended to allow value classes to be manipulated as 'Object'
  39.         // but have aliasing behavior of a value class. The intent is that you would use
  40.         // this function just before an assignment to a variable of type 'Object'. If the
  41.         // value being assigned is a mutable value class, then a shallow copy is returned
  42.         // (because value classes have copy semantics), but otherwise the object itself
  43.         // is returned.
  44.         //
  45.         // Note: VB calls this method when they're about to assign to an Object
  46.         // or pass it as a parameter. The goal is to make sure that boxed
  47.         // value types work identical to unboxed value types - ie, they get
  48.         // cloned when you pass them around, and are always passed by value.
  49.         // Of course, reference types are not cloned.
  50.         //
  51.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  52.         public static extern object GetObjectValue(object obj);
  53.        
  54.         // RunClassConstructor causes the class constructor for the given type to be triggered
  55.         // in the current domain. After this call returns, the class constructor is guaranteed to
  56.         // have at least been started by some thread. In the absence of class constructor
  57.         // deadlock conditions, the call is further guaranteed to have completed.
  58.         //
  59.         // This call will generate an exception if the specified class constructor threw an
  60.         // exception when it ran.
  61.        
  62.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  63.         private static extern void _RunClassConstructor(IntPtr type);
  64.         public static void RunClassConstructor(RuntimeTypeHandle type)
  65.         {
  66.             _RunClassConstructor(type.Value);
  67.         }
  68.        
  69.         // RunModuleConstructor causes the module constructor for the given type to be triggered
  70.         // in the current domain. After this call returns, the module constructor is guaranteed to
  71.         // have at least been started by some thread. In the absence of module constructor
  72.         // deadlock conditions, the call is further guaranteed to have completed.
  73.         //
  74.         // This call will generate an exception if the specified module constructor threw an
  75.         // exception when it ran.
  76.        
  77.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  78.         private static extern void _RunModuleConstructor(IntPtr module);
  79.        
  80.         public static void RunModuleConstructor(ModuleHandle module)
  81.         {
  82.             unsafe {
  83.                 _RunModuleConstructor(new IntPtr(module.Value));
  84.             }
  85.         }
  86.        
  87.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  88.         private static extern void _PrepareMethod(IntPtr method, RuntimeTypeHandle[] instantiation);
  89.        
  90.         // Simple (instantiation not required) method.
  91.         [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  92.         public static void PrepareMethod(RuntimeMethodHandle method)
  93.         {
  94.             _PrepareMethod(method.Value, null);
  95.         }
  96.        
  97.         // Generic method or method with generic class with specific instantiation.
  98.         [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  99.         public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] instantiation)
  100.         {
  101.             _PrepareMethod(method.Value, instantiation);
  102.         }
  103.        
  104.         // This method triggers a given delegate to be prepared. This involves preparing the
  105.         // delegate's Invoke method and preparing the target of that Invoke. In the case of
  106.         // a multi-cast delegate, we rely on the fact that each individual component was prepared
  107.         // prior to the Combine. In other words, this service does not navigate through the
  108.         // entire multicasting list.
  109.         // If our own reliable event sinks perform the Combine (for example AppDomain.DomainUnload),
  110.         // then the result is fully prepared. But if a client calls Combine himself and then
  111.         // then adds that combination to e.g. AppDomain.DomainUnload, then the client is responsible
  112.         // for his own preparation.
  113.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  114.         [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  115.         public static extern void PrepareDelegate(Delegate d);
  116.        
  117.         public static int GetHashCode(object o)
  118.         {
  119.             return Object.InternalGetHashCode(o);
  120.         }
  121.        
  122.         public static new bool Equals(object o1, object o2)
  123.         {
  124.             return Object.InternalEquals(o1, o2);
  125.         }
  126.        
  127.         public static int OffsetToStringData {
  128.             get {
  129.                 // Number of bytes from the address pointed to by a reference to
  130.                 // a String to the first 16-bit character in the String. Skip
  131.                 // over the MethodTable pointer, String capacity, & String
  132.                 // length. Of course, the String reference points to the memory
  133.                 // after the sync block, so don't count that.
  134.                 // This property allows C#'s fixed statement to work on Strings.
  135.                 // On 64 bit platforms, this should be 16.
  136.                 #if WIN32
  137.                 return 12;
  138.                 #else
  139.                 return 16;
  140.                 #endif
  141.             }
  142.         }
  143.        
  144.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  145.         [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  146.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
  147.         public static extern void ProbeForSufficientStack();
  148.        
  149.         // This method is a marker placed immediately before a try clause to mark the corresponding catch and finally blocks as
  150.         // constrained. There's no code here other than the probe because most of the work is done at JIT time when we spot a call to this routine.
  151.         [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  152.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
  153.         public static void PrepareConstrainedRegions()
  154.         {
  155.             ProbeForSufficientStack();
  156.         }
  157.        
  158.         // When we detect a CER with no calls, we can point the JIT to this non-probing version instead
  159.         // as we don't need to probe.
  160.         [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  161.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
  162.         public static void PrepareConstrainedRegionsNoOP()
  163.         {
  164.         }
  165.        
  166.         public delegate void TryCode(object userData);
  167.        
  168.         public delegate void CleanupCode(object userData, bool exceptionThrown);
  169.        
  170.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  171.         [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  172.         public static extern void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, object userData);
  173.        
  174.         [PrePrepareMethod()]
  175.         static internal void ExecuteBackoutCodeHelper(object backoutCode, object userData, bool exceptionThrown)
  176.         {
  177.             ((CleanupCode)backoutCode)(userData, exceptionThrown);
  178.         }
  179.        
  180.         [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  181.         [HostProtection(Synchronization = true)]
  182.         static internal void ExecuteCodeWithLock(object lockObject, TryCode code, object userState)
  183.         {
  184.             ExecuteWithLockHelper execHelper = new ExecuteWithLockHelper(lockObject, code, userState);
  185.             ExecuteCodeWithGuaranteedCleanup(s_EnterMonitor, s_ExitMonitor, execHelper);
  186.         }
  187.        
  188.         private static TryCode s_EnterMonitor = new TryCode(EnterMonitorAndTryCode);
  189.         private static CleanupCode s_ExitMonitor = new CleanupCode(ExitMonitorOnBackout);
  190.        
  191.         private static void EnterMonitorAndTryCode(object helper)
  192.         {
  193.             ExecuteWithLockHelper execHelper = (ExecuteWithLockHelper)helper;
  194.             BCLDebug.Assert(execHelper != null, "ExecuteWithLockHelper is null");
  195.             BCLDebug.Assert(execHelper.m_lockObject != null, "LockObject is null");
  196.             BCLDebug.Assert(execHelper.m_userCode != null, "UserCode is null");
  197.            
  198.             Monitor.ReliableEnter(execHelper.m_lockObject, ref execHelper.m_tookLock);
  199.             execHelper.m_userCode(execHelper.m_userState);
  200.         }
  201.        
  202.         [PrePrepareMethod()]
  203.         private static void ExitMonitorOnBackout(object helper, bool exceptionThrown)
  204.         {
  205.             ExecuteWithLockHelper execHelper = (ExecuteWithLockHelper)helper;
  206.             BCLDebug.Assert(execHelper != null, "ExecuteWithLockHelper is null");
  207.             BCLDebug.Assert(execHelper.m_lockObject != null, "LockObject is null");
  208.            
  209.             if (execHelper.m_tookLock)
  210.                 Monitor.Exit(execHelper.m_lockObject);
  211.         }
  212.        
  213.         class ExecuteWithLockHelper
  214.         {
  215.             internal object m_lockObject;
  216.             internal bool m_tookLock;
  217.             internal TryCode m_userCode;
  218.             internal object m_userState;
  219.            
  220.             internal ExecuteWithLockHelper(object lockObject, TryCode userCode, object userState)
  221.             {
  222.                 m_lockObject = lockObject;
  223.                 m_userCode = userCode;
  224.                 m_userState = userState;
  225.             }
  226.            
  227.         }
  228.     }
  229. }

Developer Fusion