Archive for February, 2010
Bracketing Operations With IDisposable
I learned a fun little .NET trick today at work, figured I’d pass it along. This is probably a well-known pattern, but I don’t know its name.
The Problem
Say you have a pair of functions that bracket other operations you want to do. For example, you must first call BeginRender() before you call RenderModel(), and after you’re all done, you need to call EndRender(). Another example would be a EnterLock() on a critical section, that must be accompanied by a LeaveLock(). I’ll call these bracketing functions simply “BeginX” and “EndX” for the purposes of this article.
The problem is that the caller must not only remember to call EndX, but must do so even in case of an exception, to avoid blocking the system.
The Solution: IDisposable
What we’re doing here, really, is acquiring and releasing a resource. The .NET Framework already has a pattern for that, and it’s called IDisposable. Ok, that’s not much of a trick in itself. What I learned today was a little twist on the concept.
The trick is simple:
- Create a private inner class that implements IDisposable.
- Return a new’d instance of this class in BeginX.
- In the instance’s Dispose(), have it call the private EndX.
- Callers can simply wrap the ‘handle’ in a using declaration for cleanup.
It’s obvious in retrospect, and it’s clean. The ‘using’ guarantees calling EndX even in case of an exception. And in leveraging IDisposable we can build on top of the C# programmer’s instinct to wrap usages of IDisposable objects in ‘using’ constructs. As a fallback, we can rely on tools like CodeRush to catch it as we type (or FxCop as a fallback).
Implementation
First, we need a fun little helper base class.
public abstract class DisposerBase<T> : IDisposable
{
bool _disposed;
T _owner;
public DisposerBase(T owner)
{ _owner = owner; }
public void Dispose()
{
Debug.Assert(!_disposed);
_disposed = true;
OnDispose(_owner);
}
protected abstract void OnDispose(T owner);
}
Here’s a sample class that demonstrates the IDisposable-bracket pattern. Note the inner class that has access to private methods, which we use to call EndX. This method is private so that the only way to close the bracket is to call Dispose() on the handle. Simple, straightforward, consistent.
public class TransactionManager
{
bool _inTransaction;
public IDisposable BeginTransaction()
{
Debug.Assert(!_inTransaction);
Console.WriteLine("Begin Transaction");
_inTransaction = true;
// ... do other transaction setup here ...
// caller must dispose this when done
return new TransactionDisposer(this);
}
private void EndTransaction(TransactionDisposer state)
{
Debug.Assert(_inTransaction);
Console.WriteLine("End Transaction");
// ... do transaction cleanup here ...
// (state could provide more context if needed)
_inTransaction = false;
}
#region TransactionDisposer
class TransactionDisposer : DisposerBase<TransactionManager>
{
// obviously some state could go here
// (say, for more transactions in flight at once)
public TransactionDisposer(TransactionManager owner)
: base(owner) { }
protected override void OnDispose(TransactionManager owner)
{ owner.EndTransaction(this); }
}
#endregion
public void DoSomeAction(string actionName)
{
Debug.Assert(_inTransaction);
// ... do the action ...
Console.WriteLine(" Action performed: " + actionName);
}
}
Note that this is a very simple example that only permits one transaction in flight at once. If we wanted to do more, we could have a Dictionary that maps outstanding transactions to pending state, or we could just put the state directly into the TransactionDisposer. I’ve noted this in the comments.
Now, it’s a bit of typing to implement this disposer, but that’s what snippets are for, right? Bracketed code like this isn’t overwhelmingly common either, so it shouldn’t be a big deal. Still, I have to say I miss my old friend #define from the C world sometimes. Not often. I’m looking forward to a future version of the C# compiler that lets us plug into the AST directly and codegen as we go.
Anyway, here is an example usage of this pattern:
var transactionManager = new TransactionManager();
using (var handle = transactionManager.BeginTransaction())
{
transactionManager.DoSomeAction("action 1");
}
Implicit Chaining
There is one interesting benefit that comes from this: implicit chaining.
Say you have a higher level class that provides additional functionality within its own BeginX. Perhaps it calls BeginRender() and then immediately sets some default states. Rather than having to create a new inner class to manage the bracketing, you can simply return the result of BeginRender, and the caller will not know the difference.
Let’s extend the above example in this way.
public class RequestManager
{
TransactionManager _transactionManager;
public RequestManager(TransactionManager transactionManager)
{ _transactionManager = transactionManager; }
public IDisposable BeginRequest(string initialActionName)
{
var handle = _transactionManager.BeginTransaction();
_transactionManager.DoSomeAction(initialActionName);
return handle;
}
}
See how it chains the TransactionManager’s bracketed calls through itself? We could have gone through the trouble of making an inner RequestDisposer class and a private EndRequest and all that, using the IDisposable from TransactionManager as the state, but why bother? Just chain it along. When the caller disposes the handle, it routes straight through to the TransactionManager, which is all we needed.
Some sample usage:
var requestManager = new RequestManager(transactionManager);
using (var handle = requestManager.BeginRequest("action 2"))
{
transactionManager.DoSomeAction("action 3");
}
Of course, if RequestManager has to do anything special in its EndX, then we’ll have to go and add that inner class after all. It’s a nice shortcut otherwise.
The output from both examples looks like this:
Begin Transaction Action performed: action 1 End Transaction Begin Transaction Action performed: action 2 Action performed: action 3 End Transaction
Easy huh?
Performance Implications
It’s worth asking what the costs of this method are. How does this compare to simply calling BeginX and EndX?
Let’s consider this sample usage again:
using (var handle = transactionManager.BeginTransaction())
{
transactionManager.DoSomeAction("action 1");
}
This is syntactic sugar (I loathe this term but it is unfortunately apt) that the compiler translates into something like this:
IDisposable handle = transactionManager.BeginTransaction();
try
{
transactionManager.DoSomeAction("action 1");
}
finally
{
if (handle != null)
handle.Dispose();
}
Note that the runtime does not do anything special with IDisposable types. They are created and collected exactly the same as any other type. And as a result, this is almost identical to what we’d have to do for a manual BeginX/EndX:
transactionManager.BeginTransaction();
try
{
transactionManager.DoSomeAction("action 1");
}
finally
{
transactionmanager.EndTransaction();
}
Now, this is assuming no state needs to be maintained in the handle. If it were, then we’d have to store it in a local and pass it into EndTransaction, and the BeginX/EndX pattern would almost exactly match the disposer pattern.
So: the cost of the disposer pattern over BeginX/EndX is that an extra object gets new’d up, with a bit of glue logic that runs. Insignificant, not worth worrying about.
Even if it did have a real cost, I’d still not worry about it. This is intended to be used in bracket patterns where resources are being allocated and freed. The cost of the underlying resource management is going to mask whatever minor cost the disposer adds.
The cleaner, more maintainable, and statically-analyzable code that results is an easy win.
Dungeon Siege Page Posted
By popular request, I just posted a new page that has everything I could find that I’ve done related to Dungeon Siege. It’s got the good, the bad, and the ugly. A large, memorable chapter of my early game development life.
Until now, this stuff has been scattered all over four different defunct websites in a mess of broken links. This new page fixes all of that for good.
I worked at Gas Powered Games between November 1999 and October 2003, back when it was a fresh startup. In that time, I lectured and wrote about some of the technology we used to build Dungeon Siege and later projects. I also released specifications for some of the internals of the engine to help the mod community.
This page collects all of my published Dungeon Siege work.
…continued here


