March 30, 2010 0

Thoughts on SlimDX 2: Object Lifetime

By Josh Petrie in Blog

This will likely be my last post on the subject of the major changes coming in SlimDX 2 for a little while. My last few posts have focused on issues we’re fairly certain will be relevant to the new API (as will this post) — but we don’t have everything planned out yet. We have a few ideas we’d like to experiment with, but we’re going to have to take some time to prototype them and mess around before we can commit to any one solution. Indeed, there are even a few unanswered questions about the topic I’m going to talk about today.

That topic is how we’re not going to use IDisposable any longer.

More specifically, we’re not going to use it as much. Almost every SlimDX 1 object implements IDisposable, because IDisposable is all about cleaning up unmanaged resources and SlimDX objects are, for the most part, exactly that. But the sort of resources IDisposable is geared towards are those with very explicit lifetimes: you create it, do your thing, and then Dispose() of it. C# using-blocks allow you to implement this exact pattern for locally-held objects quite efficiently.

Long-time readers will recall that our IDisposable wrappers around COM objects have caused us a lot of trouble in the past, largely because the interface’s contract does not really jive with COM’s reference counting. To account for this, we implemented an object table based loosely on the same principles that the .NET RCW uses — specifically, we tried to maintain exactly one COM reference to any object known to SlimDX so that we could do the correct thing when Dispose() was called. This eventually led us to an overly-complicated system burdened with multiple creation code paths and inconsistent ownership semantics.

Our solution is to, essentially, side-step the issue entirely and just expose the reference counting directly. All SlimDX 2 objects that are backed by actual COM interfaces implement IComObject, which provides the familiar-looking methods AddReference() and Release(). For the trivial scenarios where you just want quick, scoped access to a COM object, we’ll be providing a simple IDisposable utility wrapper you can use in conjunction with a using-block to automatically drop the reference count when appropriate.

While it first might seem like this change is a step backwards, we think that it’s an improvement in the long run: it obviates the need for the exceedingly complex object ownership rules that existed with SlimDX 1 (which, we suspect, most of our users were getting wrong). Plus, it makes the SlimDX ownership semantics match those of the already-familiar native API.

Tags: , , ,

March 24, 2010 1

Ada Lovelace Day 2010: Tess Ferrandez

By Josh Petrie in Blog

Today is March 24th: Ada Lovelace Day. I first heard about this event last year, via a co-worker’s blog, but it was too late at the time for me to come up with a contribution myself. As it stands, I almost missed this year, too!

In any event, the purpose of Ada Lovelace Day is to write a post celebrating the achievements of women (or a particular woman) in the technology industry and thus, I would like to call out Tess Ferrandez, ASP.NET escalation engineer extraordinaire.

But this post isn’t about Ferrandez’s achievements in the domain of ASP.NET, specifically. Instead, this is about commending her for her work in educating the development community about debugging in the .NET environment. Ferrandez has been at Microsoft for more than a decade, working with .NET technology since it was in alpha, and offering her knowledge to the community at large through blog posts, podcasts, interviews and by speaking at conferences. She often discusses techniques for diagnosing obscure bugs or memory issues, providing great insight into the tools used or the systems affected — and she’s always informative, easy to follow, and extremely helpful.

I, personally, can attribute the entirety of my understanding of WinDbg and SOS directly to her, as well as a good portion of my understanding of the .NET internals. I am certainly not the only developer to have benefited from her work. So I want to congratulate you, Tess Ferrandez, on what I feel is the greatest achievement of all: teaching others through your own wisdom and experience.

Tags:

March 16, 2010 1

Hargreaves on Breaking Changes

By Josh Petrie in Blog

Shawn Hargreaves has been writing about the upcoming changes in XNA 4.0 (interesting stuff). The topic is obviously one that resonates with me given my own recent posts.

I particularly enjoyed this post. Back in 2007, when SlimDX was a young API, we had the luxury of having very few serious users. When we realized we’d screwed something up, we just changed it, and it didn’t matter how much that change would impact a client code. There were no clients.

But now, three years later, that’s no longer the case. We have quite a few users; SlimDX has been used in commercially released games and applications, and helps power internal content production tools used by professional studios like Zipper Interactive. We no longer have the luxury of implementing sweeping changes on a whim, no matter how correct they may be. We have practical realities to consider: providing sufficient advance warning and documentation. Developing upgrade paths. Transitioning deprecated versions of the API to “support mode” for an appropriate period of time.

I believe that breaking changes are for the best when they actually improve the overall health of the API. But they’re also pretty scary.

Tags: , , ,

March 14, 2010 12

Thoughts on SlimDX 2: Assembly Design

By Josh Petrie in Blog

SlimDX 1 is contained in a single, monolithic C++/CLI assembly. SlimDX 2 is structured differently: it is split up into both public and private DLLs. The public DLL, which will be directly referenced by client code, is written in C# and contains the definitions for all the interfaces, enumerations, et cetera. The private DLL, written in C++/CLI, contains the interface implementations and all our internal machinery.

The primary motivation for organizing the library in this fashion was to eliminate the problems with building “Any CPU” applications using SlimDX.

Managed applications built in “Any CPU” mode are essentially asking the CLR to load them as processes most-appropriate to the host machine: if you’re running on the x64 architecture, you get a 64-bit process. On x86, you’d get a 32-bit process.

For native code, however, the target architecture needs to be decided at compile-time, which is why there are distinct 32-bit and 64-bit versions of the SlimDX assembly. Unfortunately, you cannot load a 32-bit DLL into a 64-bit process.

If you’re using the copies of SlimDX that our installer places in the GAC, you can avoid running afoul of this problem by editing your .csproj. If you’re a user who prefers to reference the SlimDX DLLs themselves, you are out of luck. You have to pick a specific version to reference, and you have to set the machine type of your project to match.

By using a two-part distribution, we can ship a public assembly configured for “Any CPU” use. This assembly can detect whether 32- or 64-bit code would be more appropriate and load the correct private implementation DLL into your process.

This approach also allows us to write more of SlimDX in C#, which is far more pleasant language to work with than C++/CLI, and has a much better toolchain.

It also lets us improve the health of the code we do need to write in C++/CLI. Because of a peculiarity in how templates (not generics) interact with managed types, the presence of a template type anywhere in a class hierarchy results in a complete lack of IntelliSense support for that class hierarchy… but there’s a lot of redundant boilerplate code in SlimDX, exactly the kind of code one would like to use templates to write just once. We had to compromise and use macros to provide that code for SlimDX 1.

However, with the split-assembly approach — along with with our adoption of interfaces — the classes “polluted” by templates exist entirely in the private assembly and are never exposed by their concrete types; the lack of IntelliSense becomes a non-issue.

There is one small downside, unfortunately. Since the implementation DLL is loaded manually, clients who reference and ship private copies of SlimDX (that is, anyone not using the GAC version) will need to add or link the SlimDX implementation DLLs (and PDBs) in their .csproj files in order to allow the build system to copy those files into the directory of the built application.

Tags: , , ,