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(ReaderWriterLockSlim rwLock, LockMode lockMode)
: IDisposable
{
private readonly ReaderWriterLockSlim _rwLock = rwLock;
private LockMode _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,
}
}
}