Statshot-Top-Safety[1]This is the first in what should be a series of  posts about a problem I’m addressing at work.

I work on an application that is fairly old; it’s grown through accretion over the past decade.  There have been a few architectural revolutions during the process of development, but the code is still very much the Visual Studio 6-based C++ MFC application it started as.

One of the areas where we’ve made progress in the past year or so is in the introduction of smart pointers, specifically boost::shared_ptr<>.  When we upgraded to Visual Studio 2005, which has a fully standards-compliant compiler engine, we suddenly gained access to a number of modern C++ libraries, including Boost.  One of the best modules available in Boost is the smart pointer one, and the “best” (most generally useful) smart pointer in that module is boost::shared_ptr<>.

I won’t bore you with the details, but shared_ptr — a “reference-counted smart pointer” — allows you to almost completely rid yourself of the headaches of manual memory management in C++.  It wraps raw pointers in such a way that you can pass them around freely, like any other first-class object in the system, and internal logic in the shared_ptr object will track the number of references for you.  When there are no references left (all copies of the owned pointer have gone out of scope or been otherwise decomissioned) it will automatically delete the wrapped pointer.

The upshot is that this is great behavior, and very useful to us.  We’ve put them in everywhere we could do so easily, and reaped the benefits of stability by doing so.  We’d like to use them in other places, but unfortunately our architecture heavily leverages the standard Windows messaging system.

Invented for Windows 3.1 (or possibly earlier; I’m not familiar with pre-3.1 Windows) way back in the Dark Ages, the Windows messaging system is a way to modularize applications by providing a generic messaging interface.

You make calls by calling PostMessage() or SendMessage() and providing the window handle of your target, the message code you want to send, and a couple of generic parameters that carry information about what you are trying to do.  The calls look like:

LRESULT ret = ::SendMessage(hWnd, WM_MESSAGE, p1, p2);

There is then code on the receiving side that retrieves these messages and dispatches them to the appropriate handler function with the provided parameters. Voila, instant decoupled function call!

This is all great, as far as it goes.  Where the problem comes in is with the parameters.  These (in Win32) are 32-bit integers, and if what you want to send is too large to fit in two 32-bit integers you need to pass the address of the object you want to access as one of the parameters.  Once you’ve done that, you are faced with a number of problems:

  1. How do you ensure the receiver treats the pointer you’ve sent as an object of the correct type?
  2. How do you know whether or not the receiver should delete the object’s pointer after it’s done using it?
  3. How do you even know (in the case of PostMessage) that the object will even be valid by the time the receiver gets around to using it?

All of these are major issues, and unfortunately all of them are easy to get wrong and there’s no way to tell until your code hits a problem and explodes.  There are better message-passing schemes that have been invented more recently (such as signal/slot, etc.) but completely replumbing our application to support these is not an option.  We’re stuck with Windows messaging.

It would be really nice to use smart pointers for these types of calls though, wouldn’t it?  If we could properly use shared_ptr, that would eliminate issues 2 and 3.  And it would be nice to add some compile-time type safety as well to eliminate issue 1.  If you could do this, you’d have a way to pass typed arguments via the Windows messaging system without worrying about memory allocation or ownership issues, and if you made an object typing mistake, the compiler would inform you about it right away, rather than letting your users inform the customer service desk.

This is the problem I’m trying to solve.  More to come!

Update:  I may need to defer writing any more on this until I find out whether my magazine article submissions are accepted or not.  They won’t accept material that’s been previously published, even online.  I’ll keep you informed.