Thursday, August 2, 2012

Synchronization: Working with synchronized resources

Today I'm going to write again about the synchronization, but will mainly concentrate on the way of helping to avoid some code duplication, and will save some time.

In one of my previous posts I've described several ways of synchronizing access to the resource, and what we’ve pointed out there as a general (of course with exceptions) practice each synchronized resource in needs to have an associated object, used for synchronizing access to that resource only, and for nothing else.

Thinking about that I came up with the following class definition which I found very handy:

public class ConcurrentResource<T>
{ 
  private readonly Object syncRoot = new Object(); 
  public readonly T Resource; 
  
  public ConcurrentResource(T argResource) 
  {
    if (argResource == null) 
    { 
      throw new ArgumentNullException("argResource"); 
    }
    
    this.Resource = argResource; 
  }
}



The ConcurrentResource type will encapsulate the object which to the access is going to be synchronized, and will also define internally a read-only property called syncRoot, which will be used for synchronizing the access.

Using that type I found it really handy but let me describe a bit more the use of it and what methods we can add to it to make it handier to work with.

So let's imagine we want to do some action with locking that resource. The following method will be really handy here, because it will encapsulate the locking mechanism in it as you can see:

public void HandleActionInSyncronizedContext(Action argAction)
{
  if(argAction == null)
  {
    throw new ArgumentNullException("argAction");
  }
 
  lock(this.syncRoot)
  {
    argAction();
  }
}



So the method internally will handle the locking mechanism and the caller will not need to use it directly in the code. One advantage of the abstraction, is that it will be very handy when we will need to switch from lock{…} to Monitor.Enter(…) call with timeout in one place, and get it working everywhere. There are bunch of interesting methods we can add to that type, and here are few of those:

public void WaitForPulse()
{
  Monitor.Wait(this.Resource);
}
 
public void Pulse()
{
  this.HandleActionInSyncronizedContext(()=>
  {
    Monitor.PulseAll(this.Resource);
  });
}
 



As a complete example of usage of the ConcurrentResource( of T) type you can take a look to the sources of ConsoleHoster project in here.