using System; namespace System.Threading { /// Represents a lock that is used to manage access to a resource, allowing multiple threads for reading or exclusive access for writing. // Token: 0x02000053 RID: 83 public class ReaderWriterLockSlim : IDisposable { /// Initializes a new instance of the class with default property values. // Token: 0x06000474 RID: 1140 RVA: 0x000166A8 File Offset: 0x000148A8 public ReaderWriterLockSlim() { } /// Initializes a new instance of the class, specifying the lock recursion policy. /// One of the enumeration values that specifies the lock recursion policy. // Token: 0x06000475 RID: 1141 RVA: 0x000166BC File Offset: 0x000148BC public ReaderWriterLockSlim(LockRecursionPolicy recursionPolicy) { this.recursionPolicy = recursionPolicy; if (recursionPolicy != LockRecursionPolicy.NoRecursion) { throw new NotImplementedException("recursionPolicy != NoRecursion not currently implemented"); } } /// Tries to enter the lock in read mode. /// The property is and the current thread has already entered read mode. -or-The recursion number would exceed the capacity of the counter. This limit is so large that applications should never encounter it. // Token: 0x06000477 RID: 1143 RVA: 0x00016704 File Offset: 0x00014904 public void EnterReadLock() { this.TryEnterReadLock(-1); } /// Tries to enter the lock in read mode, with an optional integer time-out. /// true if the calling thread entered read mode, otherwise, false. /// The number of milliseconds to wait, or -1 () to wait indefinitely. /// The property is and the current thread has already entered the lock. -or-The recursion number would exceed the capacity of the counter. The limit is so large that applications should never encounter it. /// The value of is negative, but it is not equal to (-1), which is the only negative value allowed. // Token: 0x06000478 RID: 1144 RVA: 0x00016710 File Offset: 0x00014910 public bool TryEnterReadLock(int millisecondsTimeout) { if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeout"); } if (this.read_locks == null) { throw new ObjectDisposedException(null); } if (Thread.CurrentThread == this.write_thread) { throw new LockRecursionException("Read lock cannot be acquired while write lock is held"); } this.EnterMyLock(); ReaderWriterLockSlim.LockDetails readLockDetails = this.GetReadLockDetails(Thread.CurrentThread.ManagedThreadId, true); if (readLockDetails.ReadLocks != 0) { this.ExitMyLock(); throw new LockRecursionException("Recursive read lock can only be aquired in SupportsRecursion mode"); } readLockDetails.ReadLocks++; while (this.owners < 0 || this.numWriteWaiters != 0U) { if (millisecondsTimeout == 0) { this.ExitMyLock(); return false; } if (this.readEvent == null) { this.LazyCreateEvent(ref this.readEvent, false); } else if (!this.WaitOnEvent(this.readEvent, ref this.numReadWaiters, millisecondsTimeout)) { return false; } } this.owners++; this.ExitMyLock(); return true; } /// Tries to enter the lock in read mode, with an optional time-out. /// true if the calling thread entered read mode, otherwise, false. /// The interval to wait, or -1 milliseconds to wait indefinitely. /// The property is and the current thread has already entered the lock. -or-The recursion number would exceed the capacity of the counter. The limit is so large that applications should never encounter it. /// The value of is negative, but it is not equal to -1 milliseconds, which is the only negative value allowed.-or-The value of is greater than milliseconds. // Token: 0x06000479 RID: 1145 RVA: 0x0001681C File Offset: 0x00014A1C public bool TryEnterReadLock(TimeSpan timeout) { return this.TryEnterReadLock(ReaderWriterLockSlim.CheckTimeout(timeout)); } /// Reduces the recursion count for read mode, and exits read mode if the resulting count is 0 (zero). /// The current thread has not entered the lock in read mode. // Token: 0x0600047A RID: 1146 RVA: 0x0001682C File Offset: 0x00014A2C public void ExitReadLock() { this.EnterMyLock(); if (this.owners < 1) { this.ExitMyLock(); throw new SynchronizationLockException("Releasing lock and no read lock taken"); } this.owners--; this.GetReadLockDetails(Thread.CurrentThread.ManagedThreadId, false).ReadLocks--; this.ExitAndWakeUpAppropriateWaiters(); } /// Tries to enter the lock in write mode. /// The property is and the current thread has already entered the lock in any mode. -or-The current thread has entered read mode, so trying to enter the lock in write mode would create the possibility of a deadlock. -or-The recursion number would exceed the capacity of the counter. The limit is so large that applications should never encounter it. // Token: 0x0600047B RID: 1147 RVA: 0x00016890 File Offset: 0x00014A90 public void EnterWriteLock() { this.TryEnterWriteLock(-1); } /// Tries to enter the lock in write mode, with an optional time-out. /// true if the calling thread entered write mode, otherwise, false. /// The number of milliseconds to wait, or -1 () to wait indefinitely. /// The property is and the current thread has already entered the lock. -or-The current thread initially entered the lock in read mode, and therefore trying to enter write mode would create the possibility of a deadlock. -or-The recursion number would exceed the capacity of the counter. The limit is so large that applications should never encounter it. /// The value of is negative, but it is not equal to (-1), which is the only negative value allowed. // Token: 0x0600047C RID: 1148 RVA: 0x0001689C File Offset: 0x00014A9C public bool TryEnterWriteLock(int millisecondsTimeout) { if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeout"); } if (this.read_locks == null) { throw new ObjectDisposedException(null); } if (this.IsWriteLockHeld) { throw new LockRecursionException(); } this.EnterMyLock(); ReaderWriterLockSlim.LockDetails readLockDetails = this.GetReadLockDetails(Thread.CurrentThread.ManagedThreadId, false); if (readLockDetails != null && readLockDetails.ReadLocks > 0) { this.ExitMyLock(); throw new LockRecursionException("Write lock cannot be acquired while read lock is held"); } while (this.owners != 0) { if (this.owners == 1 && this.upgradable_thread == Thread.CurrentThread) { this.owners = -1; this.write_thread = Thread.CurrentThread; IL_178: this.ExitMyLock(); return true; } if (millisecondsTimeout == 0) { this.ExitMyLock(); return false; } if (this.upgradable_thread == Thread.CurrentThread) { if (this.upgradeEvent == null) { this.LazyCreateEvent(ref this.upgradeEvent, false); } else { if (this.numUpgradeWaiters > 0U) { this.ExitMyLock(); throw new ApplicationException("Upgrading lock to writer lock already in process, deadlock"); } if (!this.WaitOnEvent(this.upgradeEvent, ref this.numUpgradeWaiters, millisecondsTimeout)) { return false; } } } else if (this.writeEvent == null) { this.LazyCreateEvent(ref this.writeEvent, true); } else if (!this.WaitOnEvent(this.writeEvent, ref this.numWriteWaiters, millisecondsTimeout)) { return false; } } this.owners = -1; this.write_thread = Thread.CurrentThread; goto IL_178; } /// Tries to enter the lock in write mode, with an optional time-out. /// true if the calling thread entered write mode, otherwise, false. /// The interval to wait, or -1 milliseconds to wait indefinitely. /// The property is and the current thread has already entered the lock. -or-The current thread initially entered the lock in read mode, and therefore trying to enter write mode would create the possibility of a deadlock. -or-The recursion number would exceed the capacity of the counter. The limit is so large that applications should never encounter it. /// The value of is negative, but it is not equal to -1 milliseconds, which is the only negative value allowed.-or-The value of is greater than milliseconds. // Token: 0x0600047D RID: 1149 RVA: 0x00016A28 File Offset: 0x00014C28 public bool TryEnterWriteLock(TimeSpan timeout) { return this.TryEnterWriteLock(ReaderWriterLockSlim.CheckTimeout(timeout)); } /// Reduces the recursion count for write mode, and exits write mode if the resulting count is 0 (zero). /// The current thread has not entered the lock in write mode. // Token: 0x0600047E RID: 1150 RVA: 0x00016A38 File Offset: 0x00014C38 public void ExitWriteLock() { this.EnterMyLock(); if (this.owners != -1) { this.ExitMyLock(); throw new SynchronizationLockException("Calling ExitWriterLock when no write lock is held"); } if (this.upgradable_thread == Thread.CurrentThread) { this.owners = 1; } else { this.owners = 0; } this.write_thread = null; this.ExitAndWakeUpAppropriateWaiters(); } /// Tries to enter the lock in upgradeable mode. /// The property is and the current thread has already entered the lock in any mode. -or-The current thread has entered read mode, so trying to enter upgradeable mode would create the possibility of a deadlock. -or-The recursion number would exceed the capacity of the counter. The limit is so large that applications should never encounter it. // Token: 0x0600047F RID: 1151 RVA: 0x00016A98 File Offset: 0x00014C98 public void EnterUpgradeableReadLock() { this.TryEnterUpgradeableReadLock(-1); } /// Tries to enter the lock in upgradeable mode, with an optional time-out. /// true if the calling thread entered upgradeable mode, otherwise, false. /// The number of milliseconds to wait, or -1 () to wait indefinitely. /// The property is and the current thread has already entered the lock. -or-The current thread initially entered the lock in read mode, and therefore trying to enter upgradeable mode would create the possibility of a deadlock. -or-The recursion number would exceed the capacity of the counter. The limit is so large that applications should never encounter it. /// The value of is negative, but it is not equal to (-1), which is the only negative value allowed. // Token: 0x06000480 RID: 1152 RVA: 0x00016AA4 File Offset: 0x00014CA4 public bool TryEnterUpgradeableReadLock(int millisecondsTimeout) { if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeout"); } if (this.read_locks == null) { throw new ObjectDisposedException(null); } if (this.IsUpgradeableReadLockHeld) { throw new LockRecursionException(); } if (this.IsWriteLockHeld) { throw new LockRecursionException(); } this.EnterMyLock(); while (this.owners != 0 || this.numWriteWaiters != 0U || this.upgradable_thread != null) { if (millisecondsTimeout == 0) { this.ExitMyLock(); return false; } if (this.readEvent == null) { this.LazyCreateEvent(ref this.readEvent, false); } else if (!this.WaitOnEvent(this.readEvent, ref this.numReadWaiters, millisecondsTimeout)) { return false; } } this.owners++; this.upgradable_thread = Thread.CurrentThread; this.ExitMyLock(); return true; } /// Tries to enter the lock in upgradeable mode, with an optional time-out. /// true if the calling thread entered upgradeable mode, otherwise, false. /// The interval to wait, or -1 milliseconds to wait indefinitely. /// The property is and the current thread has already entered the lock. -or-The current thread initially entered the lock in read mode, and therefore trying to enter upgradeable mode would create the possibility of a deadlock. -or-The recursion number would exceed the capacity of the counter. The limit is so large that applications should never encounter it. /// The value of is negative, but it is not equal to -1 milliseconds, which is the only negative value allowed.-or-The value of is greater than milliseconds. // Token: 0x06000481 RID: 1153 RVA: 0x00016B90 File Offset: 0x00014D90 public bool TryEnterUpgradeableReadLock(TimeSpan timeout) { return this.TryEnterUpgradeableReadLock(ReaderWriterLockSlim.CheckTimeout(timeout)); } /// Reduces the recursion count for upgradeable mode, and exits upgradeable mode if the resulting count is 0 (zero). /// The current thread has not entered the lock in upgradeable mode. // Token: 0x06000482 RID: 1154 RVA: 0x00016BA0 File Offset: 0x00014DA0 public void ExitUpgradeableReadLock() { this.EnterMyLock(); this.owners--; this.upgradable_thread = null; this.ExitAndWakeUpAppropriateWaiters(); } /// Releases all resources used by the current instance of the class. /// 2 // Token: 0x06000483 RID: 1155 RVA: 0x00016BC4 File Offset: 0x00014DC4 public void Dispose() { this.read_locks = null; } /// Gets a value that indicates whether the current thread has entered the lock in read mode. /// true if the current thread has entered read mode; otherwise, false. /// 2 // Token: 0x1700004B RID: 75 // (get) Token: 0x06000484 RID: 1156 RVA: 0x00016BD0 File Offset: 0x00014DD0 public bool IsReadLockHeld { get { return this.RecursiveReadCount != 0; } } /// Gets a value that indicates whether the current thread has entered the lock in write mode. /// true if the current thread has entered write mode; otherwise, false. /// 2 // Token: 0x1700004C RID: 76 // (get) Token: 0x06000485 RID: 1157 RVA: 0x00016BE0 File Offset: 0x00014DE0 public bool IsWriteLockHeld { get { return this.RecursiveWriteCount != 0; } } /// Gets a value that indicates whether the current thread has entered the lock in upgradeable mode. /// true if the current thread has entered upgradeable mode; otherwise, false. /// 2 // Token: 0x1700004D RID: 77 // (get) Token: 0x06000486 RID: 1158 RVA: 0x00016BF0 File Offset: 0x00014DF0 public bool IsUpgradeableReadLockHeld { get { return this.RecursiveUpgradeCount != 0; } } /// Gets the total number of unique threads that have entered the lock in read mode. /// The number of unique threads that have entered the lock in read mode. // Token: 0x1700004E RID: 78 // (get) Token: 0x06000487 RID: 1159 RVA: 0x00016C00 File Offset: 0x00014E00 public int CurrentReadCount { get { return this.owners & 268435455; } } /// Gets the number of times the current thread has entered the lock in read mode, as an indication of recursion. /// 0 (zero) if the current thread has not entered read mode, 1 if the thread has entered read mode but has not entered it recursively, or n if the thread has entered the lock recursively n - 1 times. /// 2 // Token: 0x1700004F RID: 79 // (get) Token: 0x06000488 RID: 1160 RVA: 0x00016C10 File Offset: 0x00014E10 public int RecursiveReadCount { get { this.EnterMyLock(); ReaderWriterLockSlim.LockDetails readLockDetails = this.GetReadLockDetails(Thread.CurrentThread.ManagedThreadId, false); int num = ((readLockDetails != null) ? readLockDetails.ReadLocks : 0); this.ExitMyLock(); return num; } } /// Gets the number of times the current thread has entered the lock in upgradeable mode, as an indication of recursion. /// 0 if the current thread has not entered upgradeable mode, 1 if the thread has entered upgradeable mode but has not entered it recursively, or n if the thread has entered upgradeable mode recursively n - 1 times. /// 2 // Token: 0x17000050 RID: 80 // (get) Token: 0x06000489 RID: 1161 RVA: 0x00016C50 File Offset: 0x00014E50 public int RecursiveUpgradeCount { get { return (this.upgradable_thread != Thread.CurrentThread) ? 0 : 1; } } /// Gets the number of times the current thread has entered the lock in write mode, as an indication of recursion. /// 0 if the current thread has not entered write mode, 1 if the thread has entered write mode but has not entered it recursively, or n if the thread has entered write mode recursively n - 1 times. /// 2 // Token: 0x17000051 RID: 81 // (get) Token: 0x0600048A RID: 1162 RVA: 0x00016C6C File Offset: 0x00014E6C public int RecursiveWriteCount { get { return (this.write_thread != Thread.CurrentThread) ? 0 : 1; } } /// Gets the total number of threads that are waiting to enter the lock in read mode. /// The total number of threads that are waiting to enter read mode. /// 2 // Token: 0x17000052 RID: 82 // (get) Token: 0x0600048B RID: 1163 RVA: 0x00016C88 File Offset: 0x00014E88 public int WaitingReadCount { get { return (int)this.numReadWaiters; } } /// Gets the total number of threads that are waiting to enter the lock in upgradeable mode. /// The total number of threads that are waiting to enter upgradeable mode. /// 2 // Token: 0x17000053 RID: 83 // (get) Token: 0x0600048C RID: 1164 RVA: 0x00016C90 File Offset: 0x00014E90 public int WaitingUpgradeCount { get { return (int)this.numUpgradeWaiters; } } /// Gets the total number of threads that are waiting to enter the lock in write mode. /// The total number of threads that are waiting to enter write mode. /// 2 // Token: 0x17000054 RID: 84 // (get) Token: 0x0600048D RID: 1165 RVA: 0x00016C98 File Offset: 0x00014E98 public int WaitingWriteCount { get { return (int)this.numWriteWaiters; } } /// Gets a value that indicates the recursion policy for the current object. /// One of the enumeration values that specifies the lock recursion policy. // Token: 0x17000055 RID: 85 // (get) Token: 0x0600048E RID: 1166 RVA: 0x00016CA0 File Offset: 0x00014EA0 public LockRecursionPolicy RecursionPolicy { get { return this.recursionPolicy; } } // Token: 0x0600048F RID: 1167 RVA: 0x00016CA8 File Offset: 0x00014EA8 private void EnterMyLock() { if (Interlocked.CompareExchange(ref this.myLock, 1, 0) != 0) { this.EnterMyLockSpin(); } } // Token: 0x06000490 RID: 1168 RVA: 0x00016CC4 File Offset: 0x00014EC4 private void EnterMyLockSpin() { int num = 0; for (;;) { if (num < 3 && ReaderWriterLockSlim.smp) { Thread.SpinWait(20); } else { Thread.Sleep(0); } if (Interlocked.CompareExchange(ref this.myLock, 1, 0) == 0) { break; } num++; } } // Token: 0x06000491 RID: 1169 RVA: 0x00016D18 File Offset: 0x00014F18 private void ExitMyLock() { this.myLock = 0; } // Token: 0x17000056 RID: 86 // (get) Token: 0x06000492 RID: 1170 RVA: 0x00016D24 File Offset: 0x00014F24 private bool MyLockHeld { get { return this.myLock != 0; } } // Token: 0x06000493 RID: 1171 RVA: 0x00016D34 File Offset: 0x00014F34 private void ExitAndWakeUpAppropriateWaiters() { if (this.owners == 1 && this.numUpgradeWaiters != 0U) { this.ExitMyLock(); this.upgradeEvent.Set(); } else if (this.owners == 0 && this.numWriteWaiters > 0U) { this.ExitMyLock(); this.writeEvent.Set(); } else if (this.owners >= 0 && this.numReadWaiters != 0U) { this.ExitMyLock(); this.readEvent.Set(); } else { this.ExitMyLock(); } } // Token: 0x06000494 RID: 1172 RVA: 0x00016DD4 File Offset: 0x00014FD4 private void LazyCreateEvent(ref EventWaitHandle waitEvent, bool makeAutoResetEvent) { this.ExitMyLock(); EventWaitHandle eventWaitHandle; if (makeAutoResetEvent) { eventWaitHandle = new AutoResetEvent(false); } else { eventWaitHandle = new ManualResetEvent(false); } this.EnterMyLock(); if (waitEvent == null) { waitEvent = eventWaitHandle; } } // Token: 0x06000495 RID: 1173 RVA: 0x00016E10 File Offset: 0x00015010 private bool WaitOnEvent(EventWaitHandle waitEvent, ref uint numWaiters, int millisecondsTimeout) { waitEvent.Reset(); numWaiters += 1U; bool flag = false; this.ExitMyLock(); try { flag = waitEvent.WaitOne(millisecondsTimeout, false); } finally { this.EnterMyLock(); numWaiters -= 1U; if (!flag) { this.ExitMyLock(); } } return flag; } // Token: 0x06000496 RID: 1174 RVA: 0x00016E78 File Offset: 0x00015078 private static int CheckTimeout(TimeSpan timeout) { int num; try { num = checked((int)timeout.TotalMilliseconds); } catch (OverflowException) { throw new ArgumentOutOfRangeException("timeout"); } return num; } // Token: 0x06000497 RID: 1175 RVA: 0x00016EC8 File Offset: 0x000150C8 private ReaderWriterLockSlim.LockDetails GetReadLockDetails(int threadId, bool create) { int i; ReaderWriterLockSlim.LockDetails lockDetails; for (i = 0; i < this.read_locks.Length; i++) { lockDetails = this.read_locks[i]; if (lockDetails == null) { break; } if (lockDetails.ThreadId == threadId) { return lockDetails; } } if (!create) { return null; } if (i == this.read_locks.Length) { Array.Resize(ref this.read_locks, this.read_locks.Length * 2); } lockDetails = (this.read_locks[i] = new ReaderWriterLockSlim.LockDetails()); lockDetails.ThreadId = threadId; return lockDetails; } // Token: 0x04000115 RID: 277 private static readonly bool smp = Environment.ProcessorCount > 1; // Token: 0x04000116 RID: 278 private int myLock; // Token: 0x04000117 RID: 279 private int owners; // Token: 0x04000118 RID: 280 private Thread upgradable_thread; // Token: 0x04000119 RID: 281 private Thread write_thread; // Token: 0x0400011A RID: 282 private uint numWriteWaiters; // Token: 0x0400011B RID: 283 private uint numReadWaiters; // Token: 0x0400011C RID: 284 private uint numUpgradeWaiters; // Token: 0x0400011D RID: 285 private EventWaitHandle writeEvent; // Token: 0x0400011E RID: 286 private EventWaitHandle readEvent; // Token: 0x0400011F RID: 287 private EventWaitHandle upgradeEvent; // Token: 0x04000120 RID: 288 private readonly LockRecursionPolicy recursionPolicy; // Token: 0x04000121 RID: 289 private ReaderWriterLockSlim.LockDetails[] read_locks = new ReaderWriterLockSlim.LockDetails[8]; // Token: 0x02000054 RID: 84 private sealed class LockDetails { // Token: 0x04000122 RID: 290 public int ThreadId; // Token: 0x04000123 RID: 291 public int ReadLocks; } } }