Saturday, June 19, 2010

Reference Counting

Dealing with a large number of shared object, especially in large and complex projects, involve us to take care about their relationship. Consider the example below:

// Create a new enemy and point the player to it
Entity *pEnemy = new Enemy;
player.SetTarget( pEnemy );

// ..
// The enemy dies and is deleted
delete pEnemy;

The player class is keeping a pointer to the entity it is focused on, but what happens when that entity is deleted? How is the player going to know? The pointer looks the same but doesn't belong to the previous entity. This is a common case of dangling pointer because the memory location the pointer was referring to is gone or has totally changed. This is the fundamental problem of shared objects. There are several approaches to solve this problem and one of these are reference counting.

How does reference counting works? The underlying mechanism is quite simple: an object will be kept alive until someone needs it, then, when nobody needs it anymore it will be deleted. To be able to use reference counting, our shared object needs to implement two functions: AddRef and RemoveRef. Whenever any part of code acquires a pointer to the object, AddRef is called, instead, whenever any part of code is done with an object it calls RemoveRef. The object keeps track of how many references it has. AddRef increments the reference counter and RemoveRef  decrements it. Finally, when the reference count is equals to zero, the object is deleted.

To make things easy to use, one possible solution is to place all reference counting functionality into a class and let any class that inherits from it to automatically become reference-counted.

// Reference counting class declaration
class RefCounted {

public:

    RefCounted() m_iRefCount(0) {}
    virtual ~RefCounted() {}

    void AddRef();
    void RemoveRef();

    int GetRefCount() const { return m_iRefCount; }

protected:

    int m_iRefCount;
};
// Adds a reference
void RefCounted::AddRef() {

    ++m_iRefCount;
}

// Removes a reference
void RefCounted::RemoveRef() {

    if( --m_iRefCount <= 0 )
        delete this;
}

Is Reference counting capable for every shared objects situation? Unfortunately not, there are a few drawbacks to keep in mind. The most important is to remember to call AddRef and RemoveRef correctly. If in the code there is an unbalanced number of AddRef and RemoveRef calls, objects will be never destroyed or they will be destroyed prematurely due to an incorrect reference counter value. The second drawback is that objects might get destroyed a bit too easily. This implies that for certain resources as a texture or geometry, would be preferable maintaining them in memory instead to destroy them frequently because load them from the hard-disk has an high performance cost. To avoid this problem can be used a resource manager that keeps an extra reference to all the resources. Finally, the last drawback is that it causes verbose code: it will soon be filled with AddRef and RemoveRef calls everywhere hindering the reading.

Thursday, February 18, 2010

Hello world!

Before starting this blog i had two ideas about how to use it:
1. To control the minds of all visitors with a special language, and in a possible future conquer the world.
2. To open a space where i can put and share all my projects.
Unfortunately the second choise seemed more user-friendly.

Seriously, I use to start every project with a little introduction, then, Hello World!