ReaderWriterLockSlim Extensions
Make your synchronizion easier by using Read/Write extensions.
Introduction
I'm guessing plenty of people have already done this themselves. But if you haven't written Read/Write extensions for ReadWriterLockSlim
(or any other lock class), here you go.
Background
I found myself writing the following pattern way too often:
bool lockHeld = false; try { lockHeld = rwlock.EnterReadLock(); closure(); } finally { if (lockHeld) rwlock.ExitReadLock(); }
I also found myself needing a way to enter locks with timeouts in the same way. So I started by making the following extension:
public static bool EnterReadLock(this ReaderWriterLockSlim target, int? millisecondsTimeout, bool throwsOnTimeout = false) { if (millisecondsTimeout == null) target.EnterReadLock(); else if (!target.TryEnterReadLock(millisecondsTimeout.Value)) { if (throwsOnTimeout) throw new TimeoutException( "Could not gain a read lock within the timeout specified. " + "(millisecondsTimeout=" + millisecondsTimeout.Value + ") "); return false; } return true; }
Which led me to write a set of extensions that look like this:
public static bool Read(this ReaderWriterLockSlim target, Action closure, int? millisecondsTimeout = null, bool throwsOnTimeout = false) { Contract.Requires<ArgumentNullException>(closure != null); Contract.Requires<ArgumentOutOfRangeException>( millisecondsTimeout == null || millisecondsTimeout >= 0 ); bool lockHeld = false; try { lockHeld = target.EnterReadLock(millisecondsTimeout, throwsOnTimeout); closure(); } finally { if (lockHeld) target.ExitReadLock(); } return lockHeld; }
Resulting in some very flexible and robust delegated extensions.
Usage Examples
Can't be much easier than:rwlock.Read( ()=> { /* Some read operation */ } );
if( !rwlock.Read( ()=> { /* Some read operation */ }, 1000 ) )
{ // Was unable to get a read lock within 1 second?
/* Do something else */
}
int myValue = rwlock.ReadValue( ()=>
{
int value;
/* Get the value */
return value;
} );
rwlock.ReadUpgradable( ()=>
{
if(needsWrite()) { // Do verification before writing...
rwlock.Write(()=>{
/* Do write operation */
}
}
}
Download the code for more useful extensions.