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