Archive for August 5th, 2010|Daily archive page

Concepts of Reference Counting

http://www.codeproject.com/KB/cpp/rcptr.aspx

In your introduction you imply that in an implementation for reference counting the object always holds the reference counter (in your example by inheritance). This is but one possible implementation of a reference counting concept however.

A reference counter does not need to be part of an object (or a base class), and the object doesn’t even need to know about it for all it cares. The solution you provide does that. This is an approach called ‘intrusive reference counting’ because you need to ‘intrude’ on each type of object definition that you want reference counting implemented for. It is sensible to do this for an OO design when the object itself ‘knows’ that the added storage and function call levels implied cost less than the off-chance of someone accidentally forgetting to release memory, or if you don’t simply care about performance cost. If you build an application from scratch, it is perfectly reasonable to do this.

Other implementations of reference counting create specialized types of pointers (‘smart pointers’) that collectively own the reference counter object (usually just a standalone int), and destroy that object upon decrementation to 0. This is preferable in old code that you do not want to touch or when you are referencing third-party objects whose class declarations you cannot change to inherit from some base class. boost:shared_ptr implements this concept, and you can also find an almost complete example in Bjarne Stroustrup’s “The C++ Programming Language”. The disadvantage of this concept is that each smart pointer needs to hold two pointers – one to the object they point to and one to the collectively shared reference counter. It is also neccessary for the application that use these smart pointers to be aware of that fact, since they explicitely need to use the appropriate smart pointer types and may never call delete on them (which is about the only thing that ultimately distinguishes them from ‘normal’ pointers). Note that the auto_ptr type is a rather incomplete implementation of smart pointers.

Yet another approach is that you implement a memory manager that holds reference counters. I consider this the ‘most object-oriented’ approach because reference counting is really the job of a memory manager. It does afford having your own memory manager though, and most applications don’t bother with that.

I did implement this last concept in my own Pool memory manager: in this implementation the memory block object also holds a corresponding block of ‘use counters’ (which are in fact reference counters), so there is no need to individually destroy reference counter objects as they’re being destroyed along with the blocks that hold the memory for the objects being managed by the pool. The memory manager also returns it’s own specialized smart pointers.

Just wanting to give you some insight on various possible solutions. There are more, and the boost library offers quite a few variants if you’re interested.
~Stefan63/www.codeproject.com

Follow

Get every new post delivered to your Inbox.