namespace StabilityMatrix.Core.Helper; /// /// Extended with support for disposal pattern. /// public class ReaderWriterLockAdvanced : ReaderWriterLockSlim { public ReaderWriterLockAdvanced() { } public ReaderWriterLockAdvanced(LockRecursionPolicy recursionPolicy) : base(recursionPolicy) { } public DisposableLock EnterReadContext(TimeSpan timeout = default) { if (!TryEnterReadLock(timeout)) { throw new TimeoutException("Timeout waiting for read lock"); } return new DisposableLock(this, LockType.Read); } public DisposableLock EnterWriteContext(TimeSpan timeout = default) { if (!TryEnterWriteLock(timeout)) { throw new TimeoutException("Timeout waiting for write lock"); } return new DisposableLock(this, LockType.Write); } public DisposableLock EnterUpgradeableReadContext(TimeSpan timeout = default) { if (!TryEnterUpgradeableReadLock(timeout)) { throw new TimeoutException("Timeout waiting for upgradeable read lock"); } return new DisposableLock(this, LockType.UpgradeableRead); } } /// /// Wrapper for disposable lock /// public class DisposableLock : IDisposable { private readonly ReaderWriterLockAdvanced readerWriterLock; private readonly LockType lockType; public DisposableLock(ReaderWriterLockAdvanced @lock, LockType lockType) { readerWriterLock = @lock; this.lockType = lockType; } public DisposableLock UpgradeToWrite(TimeSpan timeout = default) { if (lockType != LockType.UpgradeableRead) { throw new InvalidOperationException("Can only upgrade from upgradeable read lock"); } return readerWriterLock.EnterWriteContext(timeout); } public void Dispose() { switch (lockType) { case LockType.Read: readerWriterLock.ExitReadLock(); break; case LockType.Write: readerWriterLock.ExitWriteLock(); break; case LockType.UpgradeableRead: readerWriterLock.ExitUpgradeableReadLock(); break; default: throw new ArgumentOutOfRangeException(); } GC.SuppressFinalize(this); } } public enum LockType { Read, Write, UpgradeableRead }