using System; using System.Collections; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; namespace System.Threading { /// Defines a lock that supports single writers and multiple readers. /// 2 // Token: 0x0200061A RID: 1562 [ComVisible(true)] public sealed class ReaderWriterLock : CriticalFinalizerObject { /// Initializes a new instance of the class. // Token: 0x06003909 RID: 14601 RVA: 0x000C4A18 File Offset: 0x000C2C18 public ReaderWriterLock() { this.writer_queue = new LockQueue(this); this.reader_locks = new Hashtable(); GC.SuppressFinalize(this); } // Token: 0x0600390A RID: 14602 RVA: 0x000C4A50 File Offset: 0x000C2C50 [MonoTODO] ~ReaderWriterLock() { } /// Gets a value indicating whether the current thread holds a reader lock. /// true if the current thread holds a reader lock; otherwise, false. /// 2 // Token: 0x17000B08 RID: 2824 // (get) Token: 0x0600390B RID: 14603 RVA: 0x000C4A88 File Offset: 0x000C2C88 public bool IsReaderLockHeld { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { bool flag; lock (this) { flag = this.reader_locks.ContainsKey(Thread.CurrentThreadId); } return flag; } } /// Gets a value indicating whether the current thread holds the writer lock. /// true if the current thread holds the writer lock; otherwise, false. /// 2 // Token: 0x17000B09 RID: 2825 // (get) Token: 0x0600390C RID: 14604 RVA: 0x000C4AE4 File Offset: 0x000C2CE4 public bool IsWriterLockHeld { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { bool flag; lock (this) { flag = this.state < 0 && Thread.CurrentThreadId == this.writer_lock_owner; } return flag; } } /// Gets the current sequence number. /// The current sequence number. /// 2 // Token: 0x17000B0A RID: 2826 // (get) Token: 0x0600390D RID: 14605 RVA: 0x000C4B44 File Offset: 0x000C2D44 public int WriterSeqNum { get { int num; lock (this) { num = this.seq_num; } return num; } } /// Acquires a reader lock, using an value for the time-out. /// The time-out in milliseconds. /// /// expires before the lock request is granted. /// 2 // Token: 0x0600390E RID: 14606 RVA: 0x000C4B90 File Offset: 0x000C2D90 public void AcquireReaderLock(int millisecondsTimeout) { this.AcquireReaderLock(millisecondsTimeout, 1); } // Token: 0x0600390F RID: 14607 RVA: 0x000C4B9C File Offset: 0x000C2D9C private void AcquireReaderLock(int millisecondsTimeout, int initialLockCount) { lock (this) { if (this.HasWriterLock()) { this.AcquireWriterLock(millisecondsTimeout, initialLockCount); } else { object obj = this.reader_locks[Thread.CurrentThreadId]; if (obj == null) { this.readers++; try { if (this.state < 0 || !this.writer_queue.IsEmpty) { while (Monitor.Wait(this, millisecondsTimeout)) { if (this.state >= 0) { goto IL_89; } } throw new ApplicationException("Timeout expired"); } IL_89:; } finally { this.readers--; } this.reader_locks[Thread.CurrentThreadId] = initialLockCount; this.state += initialLockCount; } else { this.reader_locks[Thread.CurrentThreadId] = (int)obj + 1; this.state++; } } } } /// Acquires a reader lock, using a value for the time-out. /// A TimeSpan specifying the time-out period. /// /// expires before the lock request is granted. /// /// specifies a negative value other than -1 milliseconds. /// 2 // Token: 0x06003910 RID: 14608 RVA: 0x000C4CE4 File Offset: 0x000C2EE4 public void AcquireReaderLock(TimeSpan timeout) { int num = this.CheckTimeout(timeout); this.AcquireReaderLock(num, 1); } /// Acquires the writer lock, using an value for the time-out. /// The time-out in milliseconds. /// /// expires before the lock request is granted. /// 2 // Token: 0x06003911 RID: 14609 RVA: 0x000C4D04 File Offset: 0x000C2F04 public void AcquireWriterLock(int millisecondsTimeout) { this.AcquireWriterLock(millisecondsTimeout, 1); } // Token: 0x06003912 RID: 14610 RVA: 0x000C4D10 File Offset: 0x000C2F10 private void AcquireWriterLock(int millisecondsTimeout, int initialLockCount) { lock (this) { if (this.HasWriterLock()) { this.state--; } else { if (this.state != 0 || !this.writer_queue.IsEmpty) { while (this.writer_queue.Wait(millisecondsTimeout)) { if (this.state == 0) { goto IL_68; } } throw new ApplicationException("Timeout expired"); } IL_68: this.state = -initialLockCount; this.writer_lock_owner = Thread.CurrentThreadId; this.seq_num++; } } } /// Acquires the writer lock, using a value for the time-out. /// The TimeSpan specifying the time-out period. /// /// expires before the lock request is granted. /// /// specifies a negative value other than -1 milliseconds. /// 2 // Token: 0x06003913 RID: 14611 RVA: 0x000C4DD0 File Offset: 0x000C2FD0 public void AcquireWriterLock(TimeSpan timeout) { int num = this.CheckTimeout(timeout); this.AcquireWriterLock(num, 1); } /// Indicates whether the writer lock has been granted to any thread since the sequence number was obtained. /// true if the writer lock has been granted to any thread since the sequence number was obtained; otherwise, false. /// The sequence number. /// 2 // Token: 0x06003914 RID: 14612 RVA: 0x000C4DF0 File Offset: 0x000C2FF0 public bool AnyWritersSince(int seqNum) { bool flag; lock (this) { flag = this.seq_num > seqNum; } return flag; } /// Restores the lock status of the thread to what it was before was called. /// A returned by . /// The thread does not have the writer lock. /// The address of is a null pointer. /// 2 // Token: 0x06003915 RID: 14613 RVA: 0x000C4E40 File Offset: 0x000C3040 public void DowngradeFromWriterLock(ref LockCookie lockCookie) { lock (this) { if (!this.HasWriterLock()) { throw new ApplicationException("The thread does not have the writer lock."); } this.state = lockCookie.ReaderLocks; this.reader_locks[Thread.CurrentThreadId] = this.state; if (this.readers > 0) { Monitor.PulseAll(this); } } } /// Releases the lock, regardless of the number of times the thread acquired the lock. /// A value representing the released lock. /// 2 // Token: 0x06003916 RID: 14614 RVA: 0x000C4ED4 File Offset: 0x000C30D4 public LockCookie ReleaseLock() { LockCookie lockCookie; lock (this) { lockCookie = this.GetLockCookie(); if (lockCookie.WriterLocks != 0) { this.ReleaseWriterLock(lockCookie.WriterLocks); } else if (lockCookie.ReaderLocks != 0) { this.ReleaseReaderLock(lockCookie.ReaderLocks, lockCookie.ReaderLocks); } } return lockCookie; } /// Decrements the lock count. /// The thread does not have any reader or writer locks. /// 2 // Token: 0x06003917 RID: 14615 RVA: 0x000C4F58 File Offset: 0x000C3158 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public void ReleaseReaderLock() { lock (this) { if (!this.HasWriterLock()) { if (this.state > 0) { object obj = this.reader_locks[Thread.CurrentThreadId]; if (obj != null) { this.ReleaseReaderLock((int)obj, 1); return; } } throw new ApplicationException("The thread does not have any reader or writer locks."); } this.ReleaseWriterLock(); } } // Token: 0x06003918 RID: 14616 RVA: 0x000C4FF0 File Offset: 0x000C31F0 private void ReleaseReaderLock(int currentCount, int releaseCount) { int num = currentCount - releaseCount; if (num == 0) { this.reader_locks.Remove(Thread.CurrentThreadId); } else { this.reader_locks[Thread.CurrentThreadId] = num; } this.state -= releaseCount; if (this.state == 0 && !this.writer_queue.IsEmpty) { this.writer_queue.Pulse(); } } /// Decrements the lock count on the writer lock. /// The thread does not have the writer lock. /// 2 // Token: 0x06003919 RID: 14617 RVA: 0x000C5070 File Offset: 0x000C3270 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public void ReleaseWriterLock() { lock (this) { if (!this.HasWriterLock()) { throw new ApplicationException("The thread does not have the writer lock."); } this.ReleaseWriterLock(1); } } // Token: 0x0600391A RID: 14618 RVA: 0x000C50CC File Offset: 0x000C32CC private void ReleaseWriterLock(int releaseCount) { this.state += releaseCount; if (this.state == 0) { if (this.readers > 0) { Monitor.PulseAll(this); } else if (!this.writer_queue.IsEmpty) { this.writer_queue.Pulse(); } } } /// Restores the lock status of the thread to what it was before calling . /// A returned by . /// The address of is a null pointer. /// 2 // Token: 0x0600391B RID: 14619 RVA: 0x000C5124 File Offset: 0x000C3324 public void RestoreLock(ref LockCookie lockCookie) { lock (this) { if (lockCookie.WriterLocks != 0) { this.AcquireWriterLock(-1, lockCookie.WriterLocks); } else if (lockCookie.ReaderLocks != 0) { this.AcquireReaderLock(-1, lockCookie.ReaderLocks); } } } /// Upgrades a reader lock to the writer lock, using an Int32 value for the time-out. /// A value. /// The time-out in milliseconds. /// /// expires before the lock request is granted. /// 2 // Token: 0x0600391C RID: 14620 RVA: 0x000C5198 File Offset: 0x000C3398 public LockCookie UpgradeToWriterLock(int millisecondsTimeout) { LockCookie lockCookie; lock (this) { lockCookie = this.GetLockCookie(); if (lockCookie.WriterLocks != 0) { this.state--; return lockCookie; } if (lockCookie.ReaderLocks != 0) { this.ReleaseReaderLock(lockCookie.ReaderLocks, lockCookie.ReaderLocks); } } this.AcquireWriterLock(millisecondsTimeout); return lockCookie; } /// Upgrades a reader lock to the writer lock, using a TimeSpan value for the time-out. /// A value. /// The TimeSpan specifying the time-out period. /// /// expires before the lock request is granted. /// /// specifies a negative value other than -1 milliseconds. /// 2 // Token: 0x0600391D RID: 14621 RVA: 0x000C5228 File Offset: 0x000C3428 public LockCookie UpgradeToWriterLock(TimeSpan timeout) { int num = this.CheckTimeout(timeout); return this.UpgradeToWriterLock(num); } // Token: 0x0600391E RID: 14622 RVA: 0x000C5244 File Offset: 0x000C3444 private LockCookie GetLockCookie() { LockCookie lockCookie = new LockCookie(Thread.CurrentThreadId); if (this.HasWriterLock()) { lockCookie.WriterLocks = -this.state; } else { object obj = this.reader_locks[Thread.CurrentThreadId]; if (obj != null) { lockCookie.ReaderLocks = (int)obj; } } return lockCookie; } // Token: 0x0600391F RID: 14623 RVA: 0x000C52A8 File Offset: 0x000C34A8 private bool HasWriterLock() { return this.state < 0 && Thread.CurrentThreadId == this.writer_lock_owner; } // Token: 0x06003920 RID: 14624 RVA: 0x000C52C8 File Offset: 0x000C34C8 private int CheckTimeout(TimeSpan timeout) { int num = (int)timeout.TotalMilliseconds; if (num < -1) { throw new ArgumentOutOfRangeException("timeout", "Number must be either non-negative or -1"); } return num; } // Token: 0x040016FD RID: 5885 private int seq_num = 1; // Token: 0x040016FE RID: 5886 private int state; // Token: 0x040016FF RID: 5887 private int readers; // Token: 0x04001700 RID: 5888 private LockQueue writer_queue; // Token: 0x04001701 RID: 5889 private Hashtable reader_locks; // Token: 0x04001702 RID: 5890 private int writer_lock_owner; } }