The Labs \ Source Viewer \ SSCLI \ System.Threading \ Monitor

  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. ** Class: Monitor
  18. **
  19. **
  20. ** Purpose: Synchronizes access to a shared resource or region of code in a multi-threaded
  21. **            program.
  22. **
  23. **
  24. =============================================================================*/
  25. namespace System.Threading
  26. {
  27.    
  28.     using System;
  29.     using System.Security.Permissions;
  30.     using System.Runtime.Remoting;
  31.     using System.Threading;
  32.     using System.Runtime.CompilerServices;
  33.     using System.Runtime.ConstrainedExecution;
  34.    
  35.     [HostProtection(Synchronization = true, ExternalThreading = true)]
  36.     [System.Runtime.InteropServices.ComVisible(true)]
  37.     public static class Monitor
  38.     {
  39. /*=========================================================================
  40.         ** Obtain the monitor lock of obj. Will block if another thread holds the lock
  41.         ** Will not block if the current thread holds the lock,
  42.         ** however the caller must ensure that the same number of Exit
  43.         ** calls are made as there were Enter calls.
  44.         **
  45.         ** Exceptions: ArgumentNullException if object is null.
  46.         =========================================================================*/       
  47.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  48.         public static extern void Enter(object obj);
  49.        
  50.         // This should be made public in a future version.
  51.         // Use a ref bool instead of out to ensure that unverifiable code must
  52.         // initialize this value to something. If we used out, the value
  53.         // could be uninitialized if we threw an exception in our prolog.
  54.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  55.         static internal extern void ReliableEnter(object obj, ref bool tookLock);
  56.        
  57.        
  58. /*=========================================================================
  59.         ** Release the monitor lock. If one or more threads are waiting to acquire the
  60.         ** lock, and the current thread has executed as many Exits as
  61.         ** Enters, one of the threads will be unblocked and allowed to proceed.
  62.         **
  63.         ** Exceptions: ArgumentNullException if object is null.
  64.         **            SynchronizationLockException if the current thread does not
  65.         **            own the lock.
  66.         =========================================================================*/       
  67.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  68.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  69.         public static extern void Exit(object obj);
  70.        
  71. /*=========================================================================
  72.         ** Similar to Enter, but will never block. That is, if the current thread can
  73.         ** acquire the monitor lock without blocking, it will do so and TRUE will
  74.         ** be returned. Otherwise FALSE will be returned.
  75.         **
  76.         ** Exceptions: ArgumentNullException if object is null.
  77.         =========================================================================*/       
  78.         public static bool TryEnter(object obj)
  79.         {
  80.             return TryEnterTimeout(obj, 0);
  81.         }
  82.        
  83. /*=========================================================================
  84.         ** Version of TryEnter that will block, but only up to a timeout period
  85.         ** expressed in milliseconds. If timeout == Timeout.Infinite the method
  86.         ** becomes equivalent to Enter.
  87.         **
  88.         ** Exceptions: ArgumentNullException if object is null.
  89.         **            ArgumentException if timeout < 0.
  90.         =========================================================================*/       
  91.         public static bool TryEnter(object obj, int millisecondsTimeout)
  92.         {
  93.             return TryEnterTimeout(obj, millisecondsTimeout);
  94.         }
  95.        
  96.         public static bool TryEnter(object obj, TimeSpan timeout)
  97.         {
  98.             long tm = (long)timeout.TotalMilliseconds;
  99.             if (tm < -1 || tm > (long)Int32.MaxValue)
  100.                 throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
  101.            
  102.             return TryEnterTimeout(obj, (int)tm);
  103.         }
  104.        
  105.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  106.         private static extern bool TryEnterTimeout(object obj, int timeout);
  107.        
  108. /*========================================================================
  109. ** Waits for notification from the object (via a Pulse/PulseAll).
  110. ** timeout indicates how long to wait before the method returns.
  111. ** This method acquires the monitor waithandle for the object
  112. ** If this thread holds the monitor lock for the object, it releases it.
  113. ** On exit from the method, it obtains the monitor lock back.
  114. ** If exitContext is true then the synchronization domain for the context
  115. ** (if in a synchronized context) is exited before the wait and reacquired
  116. **
  117.         ** Exceptions: ArgumentNullException if object is null.
  118. ========================================================================*/       
  119.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  120.         private static extern bool ObjWait(bool exitContext, int millisecondsTimeout, object obj);
  121.        
  122.         public static bool Wait(object obj, int millisecondsTimeout, bool exitContext)
  123.         {
  124.             if (obj == null)
  125.                 throw (new ArgumentNullException("obj"));
  126.             return ObjWait(exitContext, millisecondsTimeout, obj);
  127.         }
  128.        
  129.         public static bool Wait(object obj, TimeSpan timeout, bool exitContext)
  130.         {
  131.             long tm = (long)timeout.TotalMilliseconds;
  132.             if (tm < -1 || tm > (long)Int32.MaxValue)
  133.                 throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
  134.            
  135.             return Wait(obj, (int)tm, exitContext);
  136.         }
  137.        
  138.         public static bool Wait(object obj, int millisecondsTimeout)
  139.         {
  140.             return Wait(obj, millisecondsTimeout, false);
  141.         }
  142.        
  143.         public static bool Wait(object obj, TimeSpan timeout)
  144.         {
  145.             long tm = (long)timeout.TotalMilliseconds;
  146.             if (tm < -1 || tm > (long)Int32.MaxValue)
  147.                 throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
  148.            
  149.             return Wait(obj, (int)tm, false);
  150.         }
  151.        
  152.         public static bool Wait(object obj)
  153.         {
  154.             return Wait(obj, Timeout.Infinite, false);
  155.         }
  156.        
  157. /*========================================================================
  158.         ** Sends a notification to a single waiting object.
  159.         * Exceptions: SynchronizationLockException if this method is not called inside
  160.         * a synchronized block of code.
  161.         ========================================================================*/       
  162.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  163.         private static extern void ObjPulse(object obj);
  164.        
  165.         public static void Pulse(object obj)
  166.         {
  167.             if (obj == null) {
  168.                 throw new ArgumentNullException("obj");
  169.             }
  170.            
  171.             ObjPulse(obj);
  172.         }
  173. /*========================================================================
  174.         ** Sends a notification to all waiting objects.
  175.         ========================================================================*/       
  176.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  177.         private static extern void ObjPulseAll(object obj);
  178.        
  179.         public static void PulseAll(object obj)
  180.         {
  181.             if (obj == null) {
  182.                 throw new ArgumentNullException("obj");
  183.             }
  184.            
  185.             ObjPulseAll(obj);
  186.         }
  187.     }
  188. }

Developer Fusion