Monday, April 5, 2010

Should I use IDisposable for purely managed resources?

Programmer Question

Here is the scenario:



I have an object called a Transaction that needs to make sure that only one entity has permission to edit it at any given time.



In order to facilitate a long-lived lock, I have the class generating a token object that can be used to make the edits.



You would use it like this:



var transaction = new Transaction();

using (var tlock = transaction.Lock())
{
transaction.Update(data, tlock);
}


Now, I want the TransactionLock class to implement IDisposable so that its usage can be clear. But, I don't have any unmanaged resources to dispose. however, the TransctionLock object itself is a sort of "unmanaged resource" in the sense that the CLR doesn't know how to properly finalize it.



All of this would be fine and dandy, I would just use IDisposable and be done with it.



However, my issue comes when I try to do this in the finalizer:



    ~TransactionLock()
{
this.Dispose(false);
}


I want the finalizer to release the transaction from the lock, if possible. How, in the finalizer, do I detect if the parent transaction (this.transaction) has already been finalized?



Is there a better pattern I should be using?






The Transaction class looks something like this:



public sealed class Transaction
{
private readonly object lockMutex = new object();

private TransactionLock currentLock;

public TransactionLock Lock()
{
lock (this.lockMutex)
{
if (this.currentLock != null)
throw new InvalidOperationException(/* ... */);

this.currentLock = new TransactionLock(this);
return this.currentLock;
}
}

public void Update(object data, TransactionLock tlock)
{
lock (this.lockMutex)
{
this.ValidateLock(tlock);

// ...
}
}

internal void ValidateLock(TransactionLock tlock)
{
if (this.currentLock == null)
throw new InvalidOperationException(/* ... */);

if (this.currentLock != tlock)
throw new InvalidOperationException(/* ... */);
}

internal void Unlock(TransactionLock tlock)
{
lock (this.lockMutex)
{
this.ValidateLock(tlock);

this.currentLock = null;
}
}
}


Find the answer here

No comments:

Post a Comment

LinkWithin

Related Posts with Thumbnails