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

  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:    RWLock
  18. **
  19. **
  20. ** Purpose: Defines the lock that implements
  21. **          single-writer/multiple-reader semantics
  22. **
  23. **
  24. ===========================================================*/
  25. namespace System.Threading
  26. {
  27.     using System.Threading;
  28.     using System.Security.Permissions;
  29.     using System.Runtime.Remoting;
  30.     using System;
  31.     using System.Runtime.CompilerServices;
  32.     using System.Runtime.InteropServices;
  33.     using System.Runtime.ConstrainedExecution;
  34.    
  35.     [HostProtection(Synchronization = true, ExternalThreading = true)]
  36.     [ComVisible(true)]
  37.     public sealed class ReaderWriterLock : CriticalFinalizerObject
  38.     {
  39. /*
  40.         * Constructor
  41.         */       
  42.         public ReaderWriterLock()
  43.         {
  44.             PrivateInitialize();
  45.         }
  46.        
  47.         ~ReaderWriterLock()/*
  48.         * Destructor
  49.         */       
  50.         {
  51.             PrivateDestruct();
  52.         }
  53.        
  54. /*
  55.         * Property that returns TRUE if the reader lock is held
  56.         * by the current thread
  57.         */       
  58.         public bool IsReaderLockHeld {
  59.             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  60.             get { return (PrivateGetIsReaderLockHeld()); }
  61.         }
  62.        
  63. /*
  64.         * Property that returns TRUE if the writer lock is held
  65.         * by the current thread
  66.         */       
  67.         public bool IsWriterLockHeld {
  68.             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  69.             get { return (PrivateGetIsWriterLockHeld()); }
  70.         }
  71.        
  72. /*
  73.         * Property that returns the current writer sequence number.
  74.         * The caller should be a reader or writer for getting
  75.         * meaningful results
  76.         */       
  77.         public int WriterSeqNum {
  78.             get { return (PrivateGetWriterSeqNum()); }
  79.         }
  80.        
  81. /*
  82.         * Acquires reader lock. The thread will block if a different
  83.         * thread has writer lock.
  84.         */       
  85.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  86.         private extern void AcquireReaderLockInternal(int millisecondsTimeout);
  87.        
  88.         public void AcquireReaderLock(int millisecondsTimeout)
  89.         {
  90.             AcquireReaderLockInternal(millisecondsTimeout);
  91.         }
  92.        
  93.        
  94.         public void AcquireReaderLock(TimeSpan timeout)
  95.         {
  96.             long tm = (long)timeout.TotalMilliseconds;
  97.             if (tm < -1 || tm > (long)Int32.MaxValue)
  98.                 throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
  99.             AcquireReaderLockInternal((int)tm);
  100.         }
  101.        
  102. /*
  103.         * Acquires writer lock. The thread will block if a different
  104.         * thread has reader lock. It will dead lock if this thread
  105.         * has reader lock. Use UpgardeToWriterLock when you are not
  106.         * sure if the thread has reader lock
  107.         */       
  108.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  109.         private extern void AcquireWriterLockInternal(int millisecondsTimeout);
  110.        
  111.         public void AcquireWriterLock(int millisecondsTimeout)
  112.         {
  113.             AcquireWriterLockInternal(millisecondsTimeout);
  114.         }
  115.        
  116.         public void AcquireWriterLock(TimeSpan timeout)
  117.         {
  118.             long tm = (long)timeout.TotalMilliseconds;
  119.             if (tm < -1 || tm > (long)Int32.MaxValue)
  120.                 throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
  121.             AcquireWriterLockInternal((int)tm);
  122.         }
  123.        
  124.        
  125. /*
  126.         * Releases reader lock.
  127.         */       
  128.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  129.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  130.         private extern void ReleaseReaderLockInternal();
  131.        
  132.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  133.         public void ReleaseReaderLock()
  134.         {
  135.             ReleaseReaderLockInternal();
  136.         }
  137.        
  138. /*
  139.         * Releases writer lock.
  140.         */       
  141.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  142.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  143.         private extern void ReleaseWriterLockInternal();
  144.        
  145.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  146.         public void ReleaseWriterLock()
  147.         {
  148.             ReleaseWriterLockInternal();
  149.         }
  150.        
  151. /*
  152.         * Upgardes the thread to a writer. If the thread has is a
  153.         * reader, it is possible that the reader lock was
  154.         * released before writer lock was acquired.
  155.         */       
  156.         public LockCookie UpgradeToWriterLock(int millisecondsTimeout)
  157.         {
  158.             LockCookie result = new LockCookie();
  159.             FCallUpgradeToWriterLock(ref result, millisecondsTimeout);
  160.             return result;
  161.         }
  162.        
  163.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  164.         private extern void FCallUpgradeToWriterLock(ref LockCookie result, int millisecondsTimeout);
  165.        
  166.         public LockCookie UpgradeToWriterLock(TimeSpan timeout)
  167.         {
  168.             long tm = (long)timeout.TotalMilliseconds;
  169.             if (tm < -1 || tm > (long)Int32.MaxValue)
  170.                 throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
  171.             return UpgradeToWriterLock((int)tm);
  172.         }
  173.        
  174. /*
  175.         * Restores the lock status of the thread to the one it was
  176.         * in when it called UpgradeToWriterLock.
  177.         */       
  178.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  179.         private extern void DowngradeFromWriterLockInternal(ref LockCookie lockCookie);
  180.        
  181.         public void DowngradeFromWriterLock(ref LockCookie lockCookie)
  182.         {
  183.             DowngradeFromWriterLockInternal(ref lockCookie);
  184.         }
  185.        
  186. /*
  187.         * Releases the lock irrespective of the number of times the thread
  188.         * acquired the lock
  189.         */       
  190.         public LockCookie ReleaseLock()
  191.         {
  192.             LockCookie result = new LockCookie();
  193.             FCallReleaseLock(ref result);
  194.             return result;
  195.         }
  196.        
  197.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  198.         private extern void FCallReleaseLock(ref LockCookie result);
  199.        
  200. /*
  201.         * Restores the lock status of the thread to the one it was
  202.         * in when it called ReleaseLock.
  203.         */       
  204.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  205.         private extern void RestoreLockInternal(ref LockCookie lockCookie);
  206.        
  207.         public void RestoreLock(ref LockCookie lockCookie)
  208.         {
  209.             RestoreLockInternal(ref lockCookie);
  210.         }
  211.        
  212. /*
  213.         * Internal helper that returns TRUE if the reader lock is held
  214.         * by the current thread
  215.         */       
  216.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  217.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  218.         private extern bool PrivateGetIsReaderLockHeld();
  219.        
  220. /*
  221.         * Internal helper that returns TRUE if the writer lock is held
  222.         * by the current thread
  223.         */       
  224.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  225.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  226.         private extern bool PrivateGetIsWriterLockHeld();
  227.        
  228. /*
  229.         * Internal helper that returns the current writer sequence
  230.         * number. The caller should be a reader or writer for getting
  231.         * meaningful results
  232.         */       
  233.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  234.         private extern int PrivateGetWriterSeqNum();
  235.        
  236. /*
  237.         * Returns true if there were intermediate writes since the
  238.         * sequence number was obtained. The caller should be
  239.         * a reader or writer for getting meaningful results
  240.         */       
  241.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  242.         public extern bool AnyWritersSince(int seqNum);
  243.        
  244.         // Initialize state kept inside the lock
  245.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  246.         private extern void PrivateInitialize();
  247.        
  248.         // Destruct resource associated with the lock
  249.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  250.         private extern void PrivateDestruct();
  251.        
  252.         // State
  253.         #pragma warning disable 169
  254.         #pragma warning disable 414 // These fields are not used from managed.
  255.         private IntPtr _hWriterEvent;
  256.         private IntPtr _hReaderEvent;
  257.         private IntPtr _hObjectHandle;
  258.         private int _dwState = 0;
  259.         private int _dwULockID = 0;
  260.         private int _dwLLockID = 0;
  261.         private int _dwWriterID = 0;
  262.         private int _dwWriterSeqNum = 0;
  263.         private short _wWriterLevel;
  264.         #if RWLOCK_STATISTICS
  265.         // WARNING: You must explicitly #define RWLOCK_STATISTICS when you
  266.         // build in both the VM and BCL directories if you want this.
  267.         private int _dwReaderEntryCount = 0;
  268.         private int _dwReaderContentionCount = 0;
  269.         private int _dwWriterEntryCount = 0;
  270.         private int _dwWriterContentionCount = 0;
  271.         private int _dwEventsReleasedCount = 0;
  272.         #endif // RWLOCK_STATISTICS
  273.         #pragma warning restore 414
  274.         #pragma warning restore 169
  275.     }
  276. }

Developer Fusion