3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // <OWNER>Microsoft</OWNER>
8 /*============================================================
13 ** Purpose: Defines the lock that implements
14 ** single-writer/multiple-reader semantics
17 ===========================================================*/
20 namespace System.Threading {
21 using System.Threading;
22 using System.Security.Permissions;
23 using System.Runtime.Remoting;
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;
31 [HostProtection(Synchronization=true, ExternalThreading=true)]
33 public sealed class ReaderWriterLock: CriticalFinalizerObject
38 [System.Security.SecuritySafeCritical] // auto-generated
39 public ReaderWriterLock()
47 [System.Security.SecuritySafeCritical] // auto-generated
54 * Property that returns TRUE if the reader lock is held
55 * by the current thread
57 public bool IsReaderLockHeld {
58 [System.Security.SecuritySafeCritical] // auto-generated
59 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
61 return(PrivateGetIsReaderLockHeld());
66 * Property that returns TRUE if the writer lock is held
67 * by the current thread
69 public bool IsWriterLockHeld {
70 [System.Security.SecuritySafeCritical] // auto-generated
71 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
73 return(PrivateGetIsWriterLockHeld());
78 * Property that returns the current writer sequence number.
79 * The caller should be a reader or writer for getting
82 public int WriterSeqNum {
83 [System.Security.SecuritySafeCritical] // auto-generated
85 return(PrivateGetWriterSeqNum());
90 * Acquires reader lock. The thread will block if a different
91 * thread has writer lock.
93 [System.Security.SecurityCritical] // auto-generated
94 [ResourceExposure(ResourceScope.None)]
95 [MethodImplAttribute(MethodImplOptions.InternalCall)]
96 private extern void AcquireReaderLockInternal(int millisecondsTimeout);
98 [System.Security.SecuritySafeCritical] // auto-generated
99 public void AcquireReaderLock(int millisecondsTimeout)
101 AcquireReaderLockInternal(millisecondsTimeout);
105 [System.Security.SecuritySafeCritical] // auto-generated
106 public void AcquireReaderLock(TimeSpan timeout)
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);
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
120 [System.Security.SecurityCritical] // auto-generated
121 [ResourceExposure(ResourceScope.None)]
122 [MethodImplAttribute(MethodImplOptions.InternalCall)]
123 private extern void AcquireWriterLockInternal(int millisecondsTimeout);
125 [System.Security.SecuritySafeCritical] // auto-generated
126 public void AcquireWriterLock(int millisecondsTimeout)
128 AcquireWriterLockInternal(millisecondsTimeout);
131 [System.Security.SecuritySafeCritical] // auto-generated
132 public void AcquireWriterLock(TimeSpan timeout)
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);
142 * Releases reader lock.
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();
150 [System.Security.SecuritySafeCritical] // auto-generated
151 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
152 public void ReleaseReaderLock()
154 ReleaseReaderLockInternal();
158 * Releases writer lock.
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();
166 [System.Security.SecuritySafeCritical] // auto-generated
167 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
168 public void ReleaseWriterLock()
170 ReleaseWriterLockInternal();
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.
178 [System.Security.SecuritySafeCritical] // auto-generated
179 public LockCookie UpgradeToWriterLock(int millisecondsTimeout)
181 LockCookie result = new LockCookie ();
182 FCallUpgradeToWriterLock (ref result, millisecondsTimeout);
186 [System.Security.SecurityCritical] // auto-generated
187 [ResourceExposure(ResourceScope.None)]
188 [MethodImplAttribute(MethodImplOptions.InternalCall)]
189 private extern void FCallUpgradeToWriterLock(ref LockCookie result, int millisecondsTimeout);
191 public LockCookie UpgradeToWriterLock(TimeSpan timeout)
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);
200 * Restores the lock status of the thread to the one it was
201 * in when it called UpgradeToWriterLock.
203 [System.Security.SecurityCritical] // auto-generated
204 [ResourceExposure(ResourceScope.None)]
205 [MethodImplAttribute(MethodImplOptions.InternalCall)]
206 private extern void DowngradeFromWriterLockInternal(ref LockCookie lockCookie);
208 [System.Security.SecuritySafeCritical] // auto-generated
209 public void DowngradeFromWriterLock(ref LockCookie lockCookie)
211 DowngradeFromWriterLockInternal(ref lockCookie);
215 * Releases the lock irrespective of the number of times the thread
218 [System.Security.SecuritySafeCritical] // auto-generated
219 public LockCookie ReleaseLock()
221 LockCookie result = new LockCookie ();
222 FCallReleaseLock (ref result);
226 [System.Security.SecurityCritical] // auto-generated
227 [ResourceExposure(ResourceScope.None)]
228 [MethodImplAttribute(MethodImplOptions.InternalCall)]
229 private extern void FCallReleaseLock(ref LockCookie result);
232 * Restores the lock status of the thread to the one it was
233 * in when it called ReleaseLock.
235 [System.Security.SecurityCritical] // auto-generated
236 [ResourceExposure(ResourceScope.None)]
237 [MethodImplAttribute(MethodImplOptions.InternalCall)]
238 private extern void RestoreLockInternal(ref LockCookie lockCookie);
240 [System.Security.SecuritySafeCritical] // auto-generated
241 public void RestoreLock(ref LockCookie lockCookie)
243 RestoreLockInternal(ref lockCookie);
247 * Internal helper that returns TRUE if the reader lock is held
248 * by the current thread
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();
257 * Internal helper that returns TRUE if the writer lock is held
258 * by the current thread
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();
267 * Internal helper that returns the current writer sequence
268 * number. The caller should be a reader or writer for getting
271 [System.Security.SecurityCritical] // auto-generated
272 [ResourceExposure(ResourceScope.None)]
273 [MethodImplAttribute(MethodImplOptions.InternalCall)]
274 private extern int PrivateGetWriterSeqNum();
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
281 [System.Security.SecuritySafeCritical] // auto-generated
282 [ResourceExposure(ResourceScope.None)]
283 [MethodImplAttribute(MethodImplOptions.InternalCall)]
284 public extern bool AnyWritersSince(int seqNum);
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();
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();
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
323 #endif //FEATURE_RWLOCK