New Fun Blog – Scott Bilas

Take what you want, and leave the rest (just like your salad bar).

Archive for February, 2010

Bracketing Operations With IDisposable

with 14 comments

Carnaval Oruro 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:

  1. Create a private inner class that implements IDisposable.
  2. Return a new’d instance of this class in BeginX.
  3. In the instance’s Dispose(), have it call the private EndX.
  4. 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.

Written by Scott

February 9th, 2010 at 9:45 pm

Posted in .net, trick

Dungeon Siege Page Posted

without comments

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.

Dungeon SiegeI 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

Written by Scott

February 2nd, 2010 at 8:49 pm

Posted in blog, dungeon siege

Switch to our mobile site