Sunday, October 7, 2007

KSignal - A Signal and Slot (Observer Design Pattern) implementation

Signal and slots is a concept developed from Qt. It is basically a generalized implementation of the Observer pattern. The purpose of the KjellKod signal-n-slot is to have the power of Observer pattern - but made with generic function callback. The most famous implementations of Signals and Slots are made by Qt and Boost. My own implementation of signals and slots (KSignal) were made in 2006-2007 when I wanted to learn more about C++ generic function callbacks. Now it's a fully functional library that is in use in multiple projects.

My own signal-n-slot definition
The KjellKod signal-slot mechanism is a C++, cross platform compatible implementation of the Observer design pattern. Signals are basically notifications of an (observable) event. Signals are connected to Slots which each store a function callback to an object. A signal can be connected to many slots and all slots/receivers are notified when the signal is emitted.

A signal can be just a notification, or it can pass along information. This make's it very handy when creating loosely coupled software systems.

The only requirement on an objects function callback that is to be stored within a slot is that it must be able to receive the same argument(s) as the publishing signal is sending. I.e. If it is a void signal, then the slot (stored callback function) must have a zero argument list. Likewise, if the signal sends out an argument, the receiving function must have that argument type, and only that argument in its argument list. If this requirement is not adhered to, the compiler will generate an error message. I.e. signal/slot is typesafe.

Modified below: 2010-08-12
Thanks to " andy_t_roo" (Andrew)  comment below which directed me to FastDelegate which in its turn made me look at GotW 83 where Herb Sutter gives an excellent (as always) example of how to encapsulate generic callbacks.

Back when I made KSignals version 1 (dynamic memory) and version 2 (static memory for embedded systems) I had not read GotW_83: Generic Callbacks  but I'm still kind of happy that I unbeknowst of much still managed to on my own come up with something very similar, although lacking some of the finer points Herb makes.

Either way I strongly recommend you to read Herbs Gotw article since it's very, very easy read and explains better than any other function callback or function pointer text that I've read how to setup the basics that are needed for Signals and Slots. If you think this is something good, then please go ahead and use my versions and tailor make them as you please (which should be easy since they're only few lines with bare bone code)


    andy_t_roo said...

    have you seen the fast delegate library? ( -- it also implements functionality similar to boosts functional or kslots, except is extremely efficient (designed to optimize to a minimal 2 assembly instruction call)

    KjellKod said...

    Hi Andrew and thank you for your comment.

    Yes I've seen the FastDelegate and even posted comments on the article.

    Please note that the FastDelegate DOES NOT just use "two assembly instructions" it uses two assembly LINES of instructions.

    Either way the BEST reason for using signals (KSignals, Qt Signals, Boost, or FastDelegate) is NOT however for making it faster. It is very very rare that the bottlenecks is the "speed of connecting a function call" but more of general design issues.
    So your comment "except it is extremely efficient" in comparison to KSignals and Boost? Is in my opinion void and not so interesting - in fact I doubt that it is that much faster or faster at all than KSignals for calls that go to one or two slots.

    In my opinion the ONLY reason for using signals or similar is for helping in creating a loosely coupled system.

    The benefit KSignals have over FastDelegate is that the FastDelegate is in my opinion a bit overworked while KSignals is tiny and very easy to customize both for embedded systems and for systems that can afford dynamic memory