Introduction

Windows resources, like GDI handles, are hard to manage correctly without
creating leaks. This article shows how smart pointers can simplify this, and
almost eliminate a major source of errors. It continues my previous article,
Smart Pointers to boost your code,
providing a practical example for using shared_ptr. (If you are not
familiar with boost::shared_ptr, you should read it now!)

Update: While the first version was more or less like "concept art", I
brushed up the sources a bit to make the more useful. I added a
reset() function that sets the HandleRef to 0, brushed up the
sources a bit and added a special implementation for HDC's. Also, I fixed some
snippets here, and added a few things to the article.

Contents

Background will examine the problem in
detail, and discuss the common solutions.

Many resource handles encountered in Win32 programming do not fit an
object-oriented environment very well. Here is a list of problems:

How you acquire the handle determines if you have to call some cleanup
function on it. If you use CreateFont, you have to call
DeleteObject when you no longer need it. However, if you got the
HFONT from a Window, you must not delete the font.

There is no way to tell from a handle whether we should delete it or have to
leave it alone.

There are many handle types, with many different Delete/Release functions,
which must be matched exactly.

Handles have "pointer" semantics, i.e., copy constructor and assignment
create only a new reference to the actual resource. This is desirable for
performance reasons, however, this makes it complicated to use RAII in an object
oriented environment.

If you have a function returning such a handle, you must at least specify if
and when to release the handle. Things get much more complicated if the handle
is a member of the class. Take a look at this innocent code snippet:

Keeping a "bool deleteTheFont" flag together with the font
handle. (I worked with std::pair<HANDLE, bool> for a while,
but this is still a pain.)

Count the references to the font. (E.g., the copy constructor would have to
increment the reference count.)

Use some kind of internal reference counting. (This works for File, Event,
Thread, and many other handles, using DuplicateHandle. However,
this is another can of worms opening up. No such luck with GDI handles.)

The nature of handles makes them prime candidates for a reference counting
mechanism:

They act as "references to resources", but the resources themselves
cannot/should not be copied.

The same resource is reused in many places, and must not be deleted as long
as someone is using it.

It should, however, be released as soon as possible, to "play nice" with the
system resources.

These resources discussed here don't reference each other, so circular
references should virtually never appear.

Further, we would like to keep the possibility of "unmanaged" handles (i.e.,
it is not deleted automatically). This flag should be set when the smart pointer
is created (close to where we acquire the resource, because this is the place
where we know how to treat it).

The line (A) is the "magic" one: here we initialize the CFontPtr
as usual, but specify that the object should be deleted using
delete_HFONT when the last reference is gone.

Now, we can make heavy use of CFontPtr: we can use it as return
value from functions. We can have it as class member, and the default copy
constructor, assignment operator, and destructor do exactly what they
should.

Do you remember the first rule for using smart pointers? Put the resource
into a smart pointer as soon as you get it. This rule holds up here as well:
because when we get the font handle, we know exactly if it should be deleted or
not. The smart pointer will carry around this flag, and automatically "do what
we want".

There are some problems even this solution cannot solve:

Someone could delete the font behind our back.

We could create the font pointer with deleteOnRelease = false,
and then forget to delete it ourselves.

But such is life in C++, you are always free to shoot yourself in the foot
you like most.

Some problems, however, can be solved better:

Checking for a "null" font is tedious: we have to check both the smart
pointer, and the actual font:

if (m_fontPtr && *m_fontPtr) // do we have a font?

We must dereference the smart pointer any time we want to access the actual
object.

To have to write three entities (deleter, smart pointer
typedef, Create function) for any other handle type we
would like to support.

The public interface is reduced to the bare minimum. (A "good thing".)

The CreateFontPtr function has become the constructor.

An automatic cast operator allows both the if (font) test, and using the
class in a place where a HFONT is expected.

The deleter remains an associated function (not shown here).

The class was renamed from "Ptr" to "Ref", since
it syntactically cast more like a reference than a pointer.

The constructor does not specify a default parameter. This was done since no
value is the "obvious default". Further, it makes the construction explicit (so
the explicit keyword isn't really needed).

I typedef'ed the boost pointer inside the class. It occurs in
quite a few places, the typedef makes the code easier to read, but
"outside" the class, no one really needs it.

Another note: Now would be a good time to make the simplification used
below. However, I'd like to go the "safe & clean way" a bit
further.

Second, we can make both the Handle type and the Deleter a template
parameter. It's simple for the Handle, but some compilers can't handle a
function as template argument. The standard solution is to turn the Deleter
function into a functor - that is, a class that overloads
operator().

(I'll repeat a few things here for the impatient who skipped over all
that boring explanation stuff)

CHandleRefT is a template class implementing a counted reference
to a Windows resource handle. Usage rules are similar to a reference counted
smart pointer. It is used to implement a variety of Windows Resource handles,
like:

HIMAGELIST ==> CImageListRef

HMENU ==> CMenuRef

HANDLE ==> CHandleRef

HBITMAP ==> CBitmapRef

HBRUSH ==> CBrushRef

HPEN ==> CPenRef

Template parameters:

HDL: type of the resource handle (e.g., HFONT).

DELETER : a functor releasing the resources of Handle of type
HDL (e.g., a functor calling DeleteObject). The handle is passed as
void *. A custom deleter can be passed to the constructor.
However, DELETER is not a template parameter of the class (which avoids template
propagation)

Automatic vs. manual handles

When constructing a HandleRef from a raw handle, you pass a
bDeleteOnRelease flag indicating if the handle should be released
automatically when the last reference to it goes out of scope.

For an automatic handle, assign the raw handle to a HandleRef
immediately after construction, specifying bDeleteOnRelease=true.
Then, pass it around only as HandleRef. This guarantees the handle
is deleted when it is no longer used.

For a manual handle, that you will delete yourself manually, or that must not
be deleted, specify bDeleteOnRelease=false.

The idea here is that you can pass around, copy, store, or return a
HandleRef, it remembers its deletion policy.

Guidelines

Utility functions that merely receive and use a resource handle (without
storing it) may use the raw handle as argument. However, when the Handle is
stored (e.g., as a class member) or used as a return value from a function, a
HandleRef is recommended.

As an example, the CImageListRef class has the following
members:

Constructor

CImageListRef(HIMAGELIST il, bool deleteOnRelease)

Initializes a new CImageListRef.

il [HIMAGELIST]: Image list to hold

deleteOnRelease [bool]: if true, the image List il
is destroyed when the last reference to it (made through the
CImageListRef instance) goes out of scope. The correct destroy
function (ImageList_Destroy) is used.

MFC tried to solve the problem with its own wrappers. Unfortunately, they
chose to wrap the first option from the "possible solutions" above: no copy
functionality, but they pass around CFont *. This might have been a
good design decision back then, but now, it is just a pain. Consider a function
returning a CFont *. Now, there are two objects that need to be
released correctly: the Windows HFONT, and the CFont C++ object. Should you:

Delete the CFont * when you are done with it, because it was
allocated dynamically?

Not delete the CFont *, but use it only until some other class
is destroyed (because the other class "holds" the font)?

Not delete the font, but use it only in the current message handler (because
it's a temporary MFC object that is deleted in the next OnIdle
call)?

Detach the HFONT from the CFont * before deleting
it (because you have to get rid of the MFC object, but the Windows resource is
still in use somewhere)?

When turning UI code into general routines and classes, I regularly stumble
over all these four scenarios. It is not a pleasant experience, I can tell you -
so I end up using raw resource handles instead, to have "only the normal
problems".

Further, I like UI code not to be dependent on MFC, if possible. The best
code IMO is a library that relies solely on the Win32 API interface, and does
not put any requirements on the framework.

Device Contexts are the most complicated resource I've come across: There are
two cleanup functions: DeleteDC and ReleaseDC,
and the latter needs an additional parameter (the HWND the DC was
acquired from).

CDCRef is implemented as separate class, since I didn't want the complexity
of HDC to "creep" into the Other HandleRef classes. The main difference is the
constructor - instead of a flag, you directly pass the deleter:

CDCRef(hdc, CDCRef::Null()) // a CDCRef that doesn't get released automatically
CDCRef(hdc, CDCRef::Delete()) // a CDCRef to be released by DeleteDC
CDCRef(hdc, CDCRef::Release(hwnd)) // a CDCRef to be released by ReleaseDC

For ReleaseDC, the HWND is passed as parameter to the deleter. Again, we
associated all information required for cleanup with the object when it is
constructed, which is a design principle of HandleRef.

Further, CDCRef provides static member functions that wrap the Win32 API
functions that acquire a HDC. For example,
CDCRef::GetDC implements the GetDC Win32 API function,
but returns a CDCRef.

The solution provided here is not new. The idea of the article is to show
that the solution becomes very simple when using an appropriate library (about
20 lines of actual code), and how such a solution would be developed from the
initial idea to use shared_ptr.

Now, How good is the solution?

You need to know how Win32 Resources are managed

You need to know how smart pointers work

You have a slight overhead over plain Win32 code: a separately allocated
object (8 Bytes) for each managed handle, and the cleanup call is through a
function pointer.

The second is not an issue: smart pointers are such a fundamental technique
that you shouldn't be caught without. The last might be an issue when handling
lots of resources. However, such an application likely benefits most from
automated resource management, and you can keep performance under control with
using a raw handle (or a CHandleRefT<> const &) where
appropriate.

The first actually reflects a design choice: CHandleRef does not
isolate you from the underlying API, but makes it transparent and easier to use.
(MFC, in contrast, isolates you very well in the default case, and fails
misderably in all others). Additional advantage: CHandleRef is not only library
independent, it also integrates easily with other libraries.

Is a "better" solution possible?

Definitely. You still can do things wrong: release an object while it is
still selected into a device context, specify the wrong cleanup policy, or
delete the handle while it is still in use. However, a completely safe solution
would require to wrap the entire GDI API: all functions creating or using an GDI
object.

CDCRef actually show the difference between an open
wrapper (allowing access to the underlying API handles) and a close
wrapper (denying the same access).

To make CDCRef construction "foolproof" the CDCRef
constructor would have to be protected, so they can be constructed only through
dedicated functions that initialize correctly. But this requires wrappers for
all functions acquiring a DC. Further, to make CDCRef completely
foolproof, one also would have to wrap all functions accepting a DC, and remove
the operator HDC() from the class. The open wrapper leaves you some
responsibility, but you have no problems if I forgot to provide a wrapper (or
the original API is extended).

Conclusion and Thank You

Thank you all for the encouraging feedback! It is great to see the time to
write the article was well spent.

For a more formal conclusion: We have seen that

Resource Handles, as many other objects, can have a variety of destruction
policies, which are not "visible" from the handle itself

The deletion policy should be "attached" to the handle when the handle is
acquired

boost::shared_ptr provides the features to make an
implementation simple

by using some platform-specific knowledge, we can make the solution more
efficient, and less complex in terms of code, while keeping the original
interface

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Peter is tired of being called "Mr. Chen", even so certain individuals insist on it. No, he's not chinese.

Peter has seen lots of boxes you youngsters wouldn't even accept as calculators. He is proud of having visited the insides of a 16 Bit Machine.

In his spare time he ponders new ways of turning groceries into biohazards, or tries to coax South American officials to add some stamps to his passport.

Beyond these trivialities Peter works for Klippel[^], a small german company that wants to make mankind happier by selling them novel loudspeaker measurement equipment.

Where are you from?[^]Please, if you are using one of my articles for anything, just leave me a comment. Seeing that this stuff is actually useful to someone is what keeps me posting and updating them.Should you happen to not like it, tell me, too

I have to disagree with this. MFC was obviously flawed at birth. They took the Model-View-Controller scheme from Smalltalk and broke it by combining the model and controller. Consequently, unless you're very disciplined, the View and Document classes end up as a monolithic disaster, where very little of the code is reusable because the model and UI are all mixed together. This is my main gripe with MFC - it encourages appallingly bad program design.

> I think it was a bad move to include auto_ptr as the only smart pointer in the STL.

I think *everyone* on the Standards committee agrees with that. I heard that the smart pointers were stuffed up because they just ran out time. (Likewise the omission of copy_if). Note that shared_ptr was the first thing admitted into C++0x.

MFC: The first thing I did was drop their Doc/View-Model, (or simply work around it) and do the stuff "my way". I was never sure if this was "just me" or a general flaw.
For the rest (i.e. trying to abstract the Windows API) it isn't to bad considering the time it was made, hough a few choices could have been better (and GDI wrapper handles are broken IMO)

we are here to help each other get through this thing, whatever it is Vonnegut jr.

TW wrote:You may also use specialize template instead of functor, to have compiler automatically choose which API to call, when closing a handle.

I tried that initially, but the compiler expects an instantiation of the function, and the linker complainsfor a just-header-library. I guess this is just a compiler thing (should it work according to the standard?)

we are here to help each other get through this thing, whatever it is Vonnegut jr.

You are evil, don't you know?
The very moment I ponder which project to get back to next, you remind me of all the irks I have with registry wrappers. Such things should be banned

But since you asked...

Your article is one of the two I consider closest to my expectations (sorry, this sounds like a "diva copmpliment", but it's just I'm rarely satisfied, even with my own code). The only place I'd (now) use boost, would be an intrusive_ptr for the PIMPL idiom.

In general, a registry wrapper would have three API layers:

(1) Wrapping the Windows API in type-safe functions using a CHandleRef<HKEY> instead of HKEY. Open, Get, Set, Get vector of values names, childs, etc. Should be very close to the Win API in naming, argument order, etc. However, I'd use a string class for it, and it would be CString for personal preference.

(2) An extende registry key that, like yours, tracks the whole path, and provides simple "navigation". This would also be the layer that allwos using another storage (XML, Property Bag, etc.)
I would, however, use a different access rights management: keys are opened with the least REGSAM required, and track which access rights were granted and not. When another REGSAM is desired, it tries to "bump" the key to the combined requirements. This could completely isolate the user from pondering his necessary rights, without sacrificing performance or restricted environments.

(3) Data Binding to Controls (like your RegDDX), and Data Classes that "act" like a registry value. (i.e. you can assign a CString, get a value of certain type, etc.) The data classes should allow to easily build structures containing configuration values.

Only layer (1) would have to be high performance. The others can trade off quite some speed & memory for convenience.

Damn now you got me ticking...

we are here to help each other get through this thing, whatever it is Vonnegut jr.

Very well written, thanks (like your previous article)!
I like to read those contributions, which discuss a problem and show the developement of a solution. Especially when it comes to templates, it is often hard to understand the final solution, whereas it is much more instructive to follow the steps evolving from special to general.

I'd like to ask you for one more explaination: How did you get rid of the delete-operator? Where is the delete actually performed, which you removed from the custom-DELETER?

first, check the declaration of the smart pointer type: it has changed from shared_ptr<HANDLE>> (representing a HANDLE *) to shared_ptr<void> (representing a void *)

All the initial versions did allocate a new HANDLE object on the heap, store the handle itself there, and a pointer to that handle in the smart pointer.

The last version stores the handle in the smart pointer itself - as void *. Now this works only because all the handle types I'm concerned about can be stored as void *. But this sacrifice of flexibility has two advantages: better performance, and the custom deleters are simpler to write.

I could have done this step earlier, but I wanted to carry on the flexible solution as far as I could.

Helped?

we are here to help each other get through this thing, whatever it is Vonnegut jr.

I understand that the subject is "boost", but many concepts, here, does not stictly depend on boost. Boost is a huge library that may be not the case to include if you only need shared_ptr (thay can be easilly coded in a 100 lines header), but the way you solved the sharing of handles problem is really good.

I addressed the problem with a more "policy like" approach here[^], but this makes me reconsider certain choices !!

You are absolutely right, using a reference counter isn't new, there are a few articles on CP here (and now, reading your article I remember seen it before ).

A few things came together in writing the article: I've long pondered the problem and knew my requriements for a solution, I needed a "quick fix" a few days ago and could hack it together in minutes using shared_ptr, I found the process of turning it into a solution interesting enough for another article, and I could feed of the success of my previous one. It's not "very boostish", as the public interface of CHandleRef does not expose anything about boost, it could be reimplemented with any other smart pointer imlementation.

So the idea is indeed implementing a known concept with as few code as possisble, the core is less than 30 lines of actual code. It's not as flexible a a policy design (but I have some "issues" with them - see my response above about Loki), but doing the job.

we are here to help each other get through this thing, whatever it is Vonnegut jr.

Good article. I'm wondering how this idea meshes with WTL which also has a 'bShouldDelete' parameter on creation of any of the 'handle' classes. I think your code could work really well as a WTL extension.

> Second, we can make both the Handle type and the Deleter a template parameter. it's simple for the Handle, but we can't specify a function as template argument.

FYI: Actually you can. Function pointers are permissible as template arguments. It's a bit bizarre, but it's in the standard. It won't work on all compilers (eg, VC6, DMC) and functors are far more useful anyway.

I don't think WTL would like the dependency on boost. However, an "#ifdef boost (use this stuff too)" would certainly be possible.

I consider the concept (using a reference-counted entity with a custom deleter) the minimum for wrapping handles. IIRC the CSmartHandle class (here on CP, mentionend also in a post below) does that with it's own code base, so it might be easier to integrate.