New Fun Blog – Scott Bilas

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

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.

[code lang="csharp"]
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);
}
[/code]

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.

[code lang="csharp"]
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);
}
}
[/code]

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:

[code lang="csharp"]
var transactionManager = new TransactionManager();
using (var handle = transactionManager.BeginTransaction())
{
transactionManager.DoSomeAction("action 1");
}
[/code]

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.

[code lang="csharp"]
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;
}
}
[/code]

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:

[code lang="csharp"]
var requestManager = new RequestManager(transactionManager);
using (var handle = requestManager.BeginRequest("action 2"))
{
transactionManager.DoSomeAction("action 3");
}
[/code]

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:

[code]
Begin Transaction
Action performed: action 1
End Transaction
Begin Transaction
Action performed: action 2
Action performed: action 3
End Transaction
[/code]

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:

[code lang="csharp"]
using (var handle = transactionManager.BeginTransaction())
{
transactionManager.DoSomeAction("action 1");
}
[/code]

This is syntactic sugar (I loathe this term but it is unfortunately apt) that the compiler translates into something like this:

[code lang="csharp"]
IDisposable handle = transactionManager.BeginTransaction();
try
{
transactionManager.DoSomeAction("action 1");
}
finally
{
if (handle != null)
handle.Dispose();
}
[/code]

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:

[code lang="csharp"]
transactionManager.BeginTransaction();
try
{
transactionManager.DoSomeAction("action 1");
}
finally
{
transactionmanager.EndTransaction();
}
[/code]

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.

February 9th, 2010 at 9:45 pm

Posted in .net,trick

14 Responses to 'Bracketing Operations With IDisposable'

Subscribe to comments with RSS or TrackBack to 'Bracketing Operations With IDisposable'.

  1. Hmm.. not so sure if it’s a good idea to abuse IDisposable for this.. It might cause some performance degradation messing around with mechanisms that mess around with the garbage collection..

    Sander van Rossen

    10 Feb 10 at 2:16 am

  2. I don’t think this is an abuse of IDisposable. In fact I think it’s a natural extension of the pattern, right in line with how it’s intended to be used (resource management).

    I updated the post with some information on performance considerations at the bottom.

    Scott

    10 Feb 10 at 8:03 am

  3. Seems like this generates unnecessary garbage. I guess that wouldn’t be much of an issue on PC, but on the XBox it might add up quick.

    Could you get away with holding an instance of TransactionDisposer inside TransactionManager, and just using the IDisposable interface to manipulate the _inTransaction flag inside TransactionDisposer instead of TransactionManager? That way you don’t have to create a TransactionDisposer each transaction.

    BradDaBug

    10 Feb 10 at 12:33 pm

  4. Like I said in my performance notes in the post, the costs of whatever happens inside of the transaction is going to overwhelm whatever minor allocation is done with an IDisposable. That’s true whether we’re on PC or Xbox or iPhone.

    On an Xbox would you avoid using ‘foreach’ as well? Because that creates an IEnumerable every time it’s used. This is the exact type of memory usage pattern that the CLR is optimized for, and why we have the multiple generation GC, where gen 0 fits in the CPU cache.

    You could hold an instance of the disposer in the manager class if you wanted, sure. That’s just a special case of a standard pool allocation optimization. In other words, instead of new’ing up a disposer, you pull it from a preallocated queue, and recycling as you go.

    But why bother? It’s a serious premature optimization to worry about it.

    We’re talking about use patterns that the CLR is specifically optimized to handle. And, again, the cost of the actual operation being bracketed will overwhelm whatever minor cost there is in temporaries used up along the way.

    Scott

    10 Feb 10 at 1:44 pm

  5. Well at the least I would call GC.SupressFinalize at the end of your Dispose method to avoid the object from being finalized, which is (relatively) expensive.

    I’m not entirely sure if it’ll prevent the object from being promoted to the next GC generation though, it still might.

  6. Why would you SuppressFinalize on a class without a finalizer?

    Regarding which gc it ends up in – it again goes back to the relative costs of the disposer from whatever operations it is bracketing.

    Scott

    11 Feb 10 at 8:48 am

  7. If you inherit from IDispose, a finalizer is implicitly added behind the scenes

  8. That’s news to me.. Are you sure? Where did you find out about that, do you have a link?

    I just looked at an IDisposable class in Reflector, and there’s nothing finalizer-related in there. Unless you mean that the CLR is doing something deep inside, which sounds unlikely to me.

    Scott

    11 Feb 10 at 12:04 pm

  9. My mistake, I must’ve remembered wrong.
    I think it’s because all the MSDN examples have virtual dispose(bool) methods, in which case you might have a finalizer somewhere down the inheritance chain, and you’d want to supress your finalizer just in case ;)

    Sander van Rossen

    11 Feb 10 at 1:11 pm

  10. Oh good. Whew. :)

    As a side note, I really dislike finalizers. I heard that Microsoft has seen the light and is quietly phasing out their usage of them as well.

    Scott

    11 Feb 10 at 1:18 pm

  11. Yeah, finalizers are pretty bad.
    .NET doesn’t even guarantee that your finalizers are run at all! Which makes them pretty much useless for most purposes.

  12. I decided to write about this a little. See latest post.

    http://scottbilas.com/blog/finalizers-an-incomplete-pattern/

    Scott

    1 Mar 10 at 9:17 pm

  13. or python there are decorators you can use on a function or class method for that sort of thing. It’s quite nice.

    for example if you want to bracket a function in a begin/end pair you can write a begin/end decorator for a function:
    [code]
    def beginEndBracket(func):
    def wrapper(*arg):
    beginX()
    res = func(*arg)
    endX()
    return res
    return wrapper

    @being_end_bracket
    def somefunctionThatNeedsToBeBracketed():
    drawSomeSnappyDirectXStuff
    [/code]
    When you call somefunctionThatNeedsToBeBracketed() it does

    Notice the closure.

    I mostly use this for timing functions and class methods.

    terry

    2 Mar 10 at 9:44 am

  14. That isn’t quite the same as what this post is about. The closing end of an IDisposable can be chosen by the client to either dispose immediately (via a ‘using’ statement for convenience) or be handed off to another routine as a sort of handle for later closing. This is what allows the chaining, almost by accident. Your example looks like a way of doing arbitrary wrapping of function calls, instead of being forced to rely on a particular language feature that is hard coded on Dispose().

    C# doesn’t have support for arbitrary wrapping out of the box, but you can use Castle’s DynamicProxy (http://www.castleproject.org/dynamicproxy/index.html) to slice in similar aspect-oriented programming behaviors. One way we use this at work is to check thread execution permissions for given routines by sticking [AllowedThread("UI")] attributes on functions.

    Scott

    2 Mar 10 at 7:34 pm

Leave a Reply