85 lines
3.3 KiB
C#
85 lines
3.3 KiB
C#
namespace System.Threading
|
|
{
|
|
/// <summary>
|
|
/// Provides extension methods for the <see cref="ReaderWriterLockSlim"/>.
|
|
/// </summary>
|
|
public static class ReaderWriterLockSlimExtensions
|
|
{
|
|
/// <summary>
|
|
/// Acquires a read lock on a lock object that can be released with an
|
|
/// <see cref="IDisposable"/> instance.
|
|
/// </summary>
|
|
/// <param name="rwLock">The lock object.</param>
|
|
/// <param name="timeoutMilliseconds">The number of milliseconds to wait, or -1
|
|
/// (<see cref="Timeout.Infinite"/>) to wait indefinitely.</param>
|
|
/// <returns>An <see cref="IDisposable"/> instance to release the lock.</returns>
|
|
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 RWLockDisposable(rwLock, 1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquires a upgradeable read lock on a lock object that can be released with an
|
|
/// <see cref="IDisposable"/> instance. The lock can be upgraded to a write lock temporarily
|
|
/// with <see cref="GetWriteLock"/> or until the lock is released with
|
|
/// <see cref="ReaderWriterLockSlim.EnterWriteLock"/> alone.
|
|
/// </summary>
|
|
/// <param name="rwLock">The lock object.</param>
|
|
/// <param name="timeoutMilliseconds">The number of milliseconds to wait, or -1
|
|
/// (<see cref="Timeout.Infinite"/>) to wait indefinitely.</param>
|
|
/// <returns>An <see cref="IDisposable"/> instance to release the lock. If the lock was
|
|
/// upgraded to a write lock, that will be released as well.</returns>
|
|
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 RWLockDisposable(rwLock, 2);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Acquires a write lock on a lock object that can be released with an
|
|
/// <see cref="IDisposable"/> instance.
|
|
/// </summary>
|
|
/// <param name="rwLock">The lock object.</param>
|
|
/// <param name="timeoutMilliseconds">The number of milliseconds to wait, or -1
|
|
/// (<see cref="Timeout.Infinite"/>) to wait indefinitely.</param>
|
|
/// <returns>An <see cref="IDisposable"/> instance to release the lock.</returns>
|
|
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 RWLockDisposable(rwLock, 3);
|
|
}
|
|
|
|
private struct RWLockDisposable : IDisposable
|
|
{
|
|
private readonly ReaderWriterLockSlim rwLock;
|
|
private int lockMode;
|
|
|
|
public RWLockDisposable(ReaderWriterLockSlim rwLock, int lockMode)
|
|
{
|
|
this.rwLock = rwLock;
|
|
this.lockMode = lockMode;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (lockMode == 1)
|
|
rwLock.ExitReadLock();
|
|
if (lockMode == 2 && rwLock.IsWriteLockHeld) // Upgraded with EnterWriteLock alone
|
|
rwLock.ExitWriteLock();
|
|
if (lockMode == 2)
|
|
rwLock.ExitUpgradeableReadLock();
|
|
if (lockMode == 3)
|
|
rwLock.ExitWriteLock();
|
|
lockMode = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|