I have a class which manipulates a resource which is shared by multiple threads. The threads pass around control of a mutex in order to manage access to the resource. I would like to manage control of the mutex using the RAII idiom via a disposable object.
There is an additional caveat. When the class begins an operation to manipulate the resource, it is possible that the operation is no longer necessary, or may no longer be performed. This is the result of user action which occurs after the operation has been scheduled to be carried out -- no way around it unfortunately. There are many different operations which might possibly be carried out, and all of them must acquire the mutex in this way. I'm imagining it will look something like this, for example:
public void DoAnOperation()
{
using(RAIIMutex raii = new RAIIMutex(TheMutex))
{
if(ShouldContinueOperation())
{
// Do operation-specific stuff
}
}
}
However, because I'm lazy, I'd like to not have to repeat that if(ShouldContinueOperation())
statement for each operation's function. Is there a way to do this while keeping the // Do operation-specific stuff
in the body of the using
statement? That seems like the most readable way to write it. For example, I don't want something like this (I'd prefer repeating the if statement if something like this is the only alternative):
public void DoAnOperation()
{
var blaarm = new ObjectThatDoesStuffWithRAIIMutex(TheMutex, ActuallyDoAnOperation);
blaarm.DoAnOperationWithTheMutex();
}
private void ActuallyDoAnOperation()
{
// Do operation-specific stuff
}
It is not entirely clear what ShouldContinueOperation
depends on, but assuming that it can be a static function (based on the example code provided in the question), you might like something along the lines of:
public static void TryOperation(Mutex mutex, Action action)
{
using (RAIIMutex raii = new RAIIMutex(mutex))
{
if (ShouldContinueOperation())
action();
}
}
Which you can then use like:
RAIIMutex.TryOperation(TheMutex, () =>
{
// Do operation-specific stuff
});
This combines the using
and the ShouldContinueOperation
check in one line for the caller. I'm not quite sure about the readability of the lambda syntax used, but that's a matter of personal preference.