//[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("AMWD.Common.Tests")] namespace System.Threading { /// /// Provides extension methods for the . /// public static class ReaderWriterLockSlimExtensions { /// /// Acquires a read lock on a lock object that can be released with an /// instance. /// /// The lock object. /// The number of milliseconds to wait, or -1 /// () to wait indefinitely. /// An instance to release the lock. public static IDisposable GetReadLock(this ReaderWriterLockSlim rwLock, int timeoutMilliseconds = -1) { if (!rwLock.TryEnterReadLock(timeoutMilliseconds)) throw new TimeoutException("The read lock could not be acquired."); return new DisposableReadWriteLock(rwLock, LockMode.Read); } /// /// Acquires a upgradeable read lock on a lock object that can be released with an /// instance. The lock can be upgraded to a write lock temporarily /// with or until the lock is released with /// alone. /// /// The lock object. /// The number of milliseconds to wait, or -1 /// () to wait indefinitely. /// An instance to release the lock. If the lock was /// upgraded to a write lock, that will be released as well. public static IDisposable GetUpgradeableReadLock(this ReaderWriterLockSlim rwLock, int timeoutMilliseconds = -1) { if (!rwLock.TryEnterUpgradeableReadLock(timeoutMilliseconds)) throw new TimeoutException("The upgradeable read lock could not be acquired."); return new DisposableReadWriteLock(rwLock, LockMode.Upgradable); } /// /// Acquires a write lock on a lock object that can be released with an /// instance. /// /// The lock object. /// The number of milliseconds to wait, or -1 /// () to wait indefinitely. /// An instance to release the lock. public static IDisposable GetWriteLock(this ReaderWriterLockSlim rwLock, int timeoutMilliseconds = -1) { if (!rwLock.TryEnterWriteLock(timeoutMilliseconds)) throw new TimeoutException("The write lock could not be acquired."); return new DisposableReadWriteLock(rwLock, LockMode.Write); } private struct DisposableReadWriteLock : IDisposable { private readonly ReaderWriterLockSlim rwLock; private LockMode lockMode; public DisposableReadWriteLock(ReaderWriterLockSlim rwLock, LockMode lockMode) { this.rwLock = rwLock; this.lockMode = lockMode; } public void Dispose() { if (lockMode == LockMode.Read) rwLock.ExitReadLock(); if (lockMode == LockMode.Upgradable && rwLock.IsWriteLockHeld) // Upgraded with EnterWriteLock alone rwLock.ExitWriteLock(); if (lockMode == LockMode.Upgradable) rwLock.ExitUpgradeableReadLock(); if (lockMode == LockMode.Write) rwLock.ExitWriteLock(); lockMode = LockMode.None; } } private enum LockMode { None = 0, Read = 1, Upgradable = 2, Write = 3, } } }