[haiku-development] Re: Signals and Slots

  • From: Joseph Groover <looncraz@xxxxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Thu, 01 Mar 2012 19:42:11 -0600


Does these function pointer approaches support virtual inheritance? If I got it right it always points to a function of a certain base class. If thats the case this lib is only limited useful, e.q. if you have a class that is already wired and you derive this class you may have to rewire the same signal/slot or even get unexpected behaviour.


Can't speak for the other library mentioned, but my method should support most any scenario ;-) You create a Signal object to which you connect callbacks. When the signal is invoked, all the connected "slots" are called. It is rather tricky to get asynchronous call-backs operational due to the use of templates in my implementation (I'd love to see a better way...). I've not had a problem with the signal propagating down the inheritance tree, but I'll give that a test run and let you know my results.

A signal and slot mechanism is more elegant and could be as powerful as BMessages but it can't be done without additional code generation via moc or something similar. I'm also against having BMessage messaging and signal/slot in parallel, both doing the same and there should only be one system for it.

I use Sigslot to minimize verbosity and improve modularity. If you want a behavior to stop, you merely disconnect from the relevant signal. There are fewer run-time checks, though, while callback overhead is certainly minimal, it can't be ignored in performance critical situations... though it is certainly faster than going through the messaging system...

This system should support at least in app and inter app messaging but this is not possible with simple c++ (e.g. for inter process communication the methods arguments have to be marshaled into flat data, send to another process and be unmarshaled there, pretty much what the programmer is manually doing with BMessages at the moment)


This is certainly intra-app only, ATM. Integrating throughout the API would be neat - just: connect(window->closing, &MyClass::ChildWindowClosing) and ANY object can be notified when a window is going to close - or you could do it in 'c', which is even easier: connect(window->closing, &WindowClosing); Makes application development much faster!

I would not be too scared about a moc (meta object compiler) since it has some really nice side effects. For example, you almost get scripting for free; you can just signal a app and so call e.g. the GetWindowCount method without implementing any complicated scripting protocol. Furthermore, with a moc you can have introspection. This means you have detailed meta data of an object. This is e.g. useful to query an object for its scripting abilities or available methods.

Regards,
    Clemens


[You Went]
_________        ;-)... though I kinda get it... I think...
 [My Head]

Quick Example Code:

Example usage:

class BWindow{
    public:
    /*
        Signals
    */
        Signal            closing;
        Signal            hidden;

Signal1<bool&> quitRequested; // change bool to false to block window from closing
       ...
};


void WindowClosing(){
    // do something here...
}

void WindowQuitReq(bool& x){
        x = false;    // block window quit request...
}        // bad form... just an example...

int main(){
    ...
     BWindow * window = new BWindow(...);

    connect(window->closing, &WindowClosing);
    uint32 wQRID = connect(window->quitRequested, &WindowQuitReq);
... // we save the (currently non-unique) connection "id" so we can disable the callback later...

    // we no longer need to worry about blocking the window from closing:
    disconnect(window->quitRequested, wQRID);

}

At least that is how the version I posted does it. My newer version is designed to do the above and more, including (hopefully) permitting async callbacks.

--The loon

Other related posts: