While there are more complex and functional lock mechanisms, I wanted a very simple lock that would tell me if an operation was locked or not. Normally I would just have a flag that’d be true or false, but I found that it was not always easy to remember to set the flag on or off, and also to make sure the flag was set at the right place. So I came up with this class :
public class BooleanLock
{
public bool Locked { get; private set; }
public class BlockLock : IDisposable
{
private BooleanLock _parent;
public BlockLock(BooleanLock parent)
{
_parent = parent;
_parent.Locked = true;
}
#region IDisposable Members
public void Dispose()
{
_parent.Locked = false;
}
#endregion
}
public BlockLock Lock()
{
return new BlockLock(this);
}
}
Now I could use it this way :
// Declare a field as a lock
private BooleanLock _myUpdateLock = new BooleanLock();
// Check for lock
private void UpdateSomeProperty(bool reset)
{
if (_myUpdateLock.Locked)
return;
// . . .
And here’s where the lock is set :
// Part of the function is not re-entrant, so we use a lock there
private void OnSomePropertyChanged()
{
if (some-condition)
{
using (_myUpdateLock.Lock())
{
// do non-re-entrant stuff
} <-- lock is released here automatically
The big advantage here is that the C# compiler’s using-block behavior handles complex try–catch scenarios that I would otherwise have had to implement on my own.
Pretty slick idea, Nish! Thanks for sharing…
Cool idea!
Thanks for sharing.
Thanks for the idea… you might want to edit it a bit to allow for nested locking.
Cheers
Assuming there is more than one place or thread where the lock may be taken, you need to check the lock and take it in one atomic operation (this requires OS support in the thread scheduler). As implemented above, there is a race condition that can result in two threads thinking they hold the lock:
Thread A checks the lock and sees that it is not taken.
Immediately following this, thread B runs and takes the lock.
While thread B still holds the lock, thread A runs and proceeds to take the lock (it thinks the lock has not been taken–remember, it wasn’t taken when thread A checked the status).
Looks good, Nish. My Stack Overflow question on your (and my) usage of “using” and “IDisposable” might be of interest; especially Eric Lippert’s answer (although I don’t agree with him 100%… 😉
http://stackoverflow.com/questions/2101524/is-it-abusive-to-use-idisposable-and-using-as-a-means-for-getting-scoped-behavior
Hey Johann,
I don’t 100% agree with his answer either though I do get what he’s trying to say.