I wanted to have a signal/events mechanism in my engine, so first i looked up some libraries which are already implemented – less code to write and maintain is always better. I liked the Qt signal/slot mechanism, but it is slow(string based) and needs the code to be preprocessed by Qt toolchain. It works nice for GUI apps, but it’s useless when it comes to games. The second choice was libsigc++, the library used by gtk. It’s much nicer in terms of speed, and also does not require any code preprocessing, but has one big flaw: it requires the class to derive from the sigc::trackable object. This can be omitted by the usage of sigc::connection objects returned by the connect function. This in turn requires to manage those connections manually, either storing them in a container or having them as members in the given receiver class. For me this is too much hassle.
In the end I decided to implement my own signals. The goal was the ease of use of the Qt signals with the speed and native C++ implementation as in libsigc++. Since I already use FastDelegate through out my code, there was no need for implementing a delegate mechanism. The only thing that had to be done was the signals themself. The signal functionality can be divided into two categories. Emitting the signals and connecting signal handlers. The first part is pretty obvious. I have a separate template signal class depending on the number of arguments. For now I implemented signals for methods/functions with 0 up to 3 arguments(if I need a signal taking more arguments it’s pretty much copy+paste).
The second type of functionality, connecting handlers, is a little more complicated. The most important thing is that when the instance of the object connected to the given signal gets destroyed, the signal should remove the callback from it’s list of handlers. For this, C++ has a killer feature: destructors. The simplest approach, used in libsigc++, is to create a connection object that will disconnect the callback from the signal when it gets destroyed. As I stated earlier I don’t like the need to have to manage those connections manually. The solution of course is a base class(again this approach is used in libsigc++), which will manage all the connections of the derived class. The problem arises when you have a class that already derives from another class. You could use virtual inheritance but this is what I would like to avoid at all cost.
Read the rest of this entry »