Alex Rivera | Logout

How would you simplify Entering and Exiting a ReaderWriterLock?

Asked 2008-10-04T09:16:16.427
11

This seems very noisy to me. Five lines of overhead is just too much.

m_Lock.EnterReadLock()
Try
    Return m_List.Count
Finally
    m_Lock.ExitReadLock()
End Try

So how would you simply this?

Edit
Report

1 Answer

0

Since the point of a lock is to protect some piece of memory, I think it would be useful to wrap that memory in a "Locked" object, and only make it accessble through the various lock tokens (as mentioned by Mark):

// Stores a private List<T>, only accessible through lock tokens
//  returned by Read, Write, and UpgradableRead.
var lockedList = new LockedList<T>( );
using( var r = lockedList.Read( ) ) {
  foreach( T item in r.Reader )
    ...
}
using( var w = lockedList.Write( ) ) {
  w.Writer.Add( new T( ) );
}
T t = ...;
using( var u = lockedList.UpgradableRead( ) ) {
  if( !u.Reader.Contains( t ) )
    using( var w = u.Upgrade( ) )
      w.Writer.Add( t );
}

Now the only way to access the internal list is by calling the appropriate accessor.

This works particularly well for List<T>, since it already has the ReadOnlyCollection<T> wrapper. For other types, you could always create a Locked<T,T>, but then you lose out on the nice readable/writable type distinction.

One improvement might be to define the R and W types as disposable wrappers themselves, which would protected against (inadvertant) errors like:

List<T> list;
using( var w = lockedList.Write( ) )
  list = w.Writable;

//BAD: "locked" object leaked outside of lock scope
list.MakeChangesWithoutHoldingLock( );

However, this would make Locked more complicated to use, and the current version does gives you the same protection you have when manually locking a shared member.


sealed class LockedList<T> : Locked<List<T>, ReadOnlyCollection<T>> {
  public LockedList( )
answered 2008-10-18T23:47:05.333

Your Answer