better event model

Hi all,

I have talked to Zach about a better way to work with events/callbacks in OF and it became pretty clear that this will have to be tackled at some point. So here is some info and questions to get this started.

Currently OF has a very simple approach to events. There is basically code that generates events and code that handles it. More specifically ofAppRunner generates them (setup(), update(), draw(), keyPressed(), …) and user app code (testApp) handles them.

Alternatively there exists a more advanced pattern for doing this. It uses a dispatcher between the calling code and the handling code. Whenever the event occurs the dispatcher is notified which in turn calls the handler. The main advantage of this is that there can be multiple handlers and they can be dynamically added and removed. There can also be a certain order in which the handlers are called.

Say for example you want to create an equivalent to ofSimpleApp for 3D apps and you want transparently setup you very own 3D opengl context. With the dispatcher pattern you could add a draw handler before and after the usual draw() is called. Then whenever OF generates a draw event three handler are called sort of like this:
of3DApp::preDraw(), of3DApp::draw(), of3DApp::postDraw()

How to implement a dispatcher-based event model?

It would be relatively simple to roll our own or just get over it and use the-one-of-Poco. Since there is all this interest in Poco here are some words about it.

Naming conventions for event models are confusing. Poco calls handlers “monitors” , some call them “callbacks” and Actionscript calls them “listeners”. Poco calls the dispatcher “event” while Actionscript calls the object that is passed from dispatcher to handler “event”. The rest is very similar across the board.

So in Poco we would do something like this for a mouse event:

Define a class of object which will be passed to the handlers:

  
  
class mouseEvent {  
	int x;  
	int y;  
	int button;  
}  
  

Create the dispatcher:

  
  
Poco::BasicEvent<const mouseEvent> mousePressedDispatcher;  
  

Register handlers with the dispatcher:

  
  
mousePressedDispatcher += delegate(object, method);  
  
#say if we do this from ofSimpleApp::setup();  
mousePressedDispatcher += delegate(this, &ofSimpleApp::mousePressed);  
  

Trigger the dispatcher:

  
  
mousePressedDispatcher.notify( this, aMouseEvent );  
  

The actual handler looks like this:

  
  
testApp::mousePressed( const void* sender, const mouseEvent& event ) {  
	//arguments are in the event object  
	int x = event.x;  
	int y = event.y  
	int button = event.button;  
	  
	//sender is the object that notified the dispatcher  
}  
  

The short summary of all this is a dispatcher-based event model would be very powerful but all the event handlers would look different/a bit more convoluted. So in the end it is a bit of a trade off between simplicity and flexibility. It might also be possible to hide this from say ofSimpleApp and have a ofSuperDuperEventModelApp for when it is nedded.

Please let me know your thoughts/ideas/imput corrections,
yo!

I was experimenting with making OF work with poco events today. I found a way to do this in a non-disruptive way…meaning all apps based on ofSimpleApp will work just as they used to be.

I will post some files soon,

Here we go!

OF-v0.05-FAT-xcode-with-Poco-events

I have added a wiki-page to tour through the changes and ideas.

Let me know what you think,
Happy Hacking,

wow that was quick :slight_smile:

I really like poco events, so I think this might be a great way to go.

downloading… will let you know.

thanks!

Hey stefan

This is really usefull, I’ve tested it under linux and it works without problem just by substituting the lib files.

We can use it not only internally in OF but it’s a really good way to structure applications, instead of calling other objects from the testApp update, draw, mousePressed… you can just register the objects that draw themselves to the draw event (perhaps the drawing order can be an issue for this) or that, which process key or mouse input to the key or mouse events.

We can implement events in other modules. For example: the videograbbing and videoplayer modules can allow to register listeners for a newFrame event.

That way any processing that you need to do to the incoming frames can be done in the background without having to create an explicit thread, just by having a class that registers to that event and do the processing to any new frame. Then that class can implement the isNewFrame flag so the main thread knows when new proccessed data is waiting.

I’ll try to do this with the videograbber or videoplayer module and post an example.

Hi

I’m trying to adapt videoGrabber and videoPlayer to work with events but I have some doubts…

I need this modules to work using a callback and not all of them do it:

videoGrabber

linuc: it can be done without problem using the dma version that uses callbacks.

windows/videoInput: internally videoInput uses callbacks so it can be easily modified to register an external callback that then generates the poco event

quicktime: For what I understand in the code it doesn’t use callbacks, instead it changes first pixel alpha to 0 whenever there’s a new frame, and verifies that pixel every time grabFrame is called, but as it’s not blocking I suppose there’s a way to register a callback. Does anyone know if this can be done?

videoPlayer

windows/mac it already uses a callback so it can be done without problem.

linux It just calculates the time between frames and reads the next frame whenever it’s needed so for this one I supose the solution is registering some kind of callback to a timer that gets called for every new frame.

I’ve uploaded some new code added to stefan original one. It’s just some classes that you can extend to easily register your objects as event listeners.

They are:

ofSetupListener
ofUpdateListener
ofDrawListener
ofMouseListener
ofKeyListener

So for example if you are making a class that reads mouse events and draws itself (this can be useful for the UI module) you just have to make your class inherit from ofDrawListener and ofMouseListener and implement there the draw(), mousePressed(), mouseReleased(), mouseMoved() and mouseDragged() methods.

Then you just need to create a variable in testApp.h of your new class and it’s methods will be automatically called whenever the events happen, no calls from the main app are needed.

The classes are in the app directory and there’s a modified version of the eventsExample in apps/eventsRemake directory. I’ve just copied the source to the original stefan code as I use linux/eclipse so publishing my project will be useless for most people. I haven’t tested under mac but it should work without problem. I’ll post a codeblocks version soon.

You can download from:

http://65.111.166.199/openframeworks/of-v0.05-xcode-FAT-poco-events.zip

wow arturo that is really interesting and it cleans up one of the larger issues I had with the original implementation, the fact that there were all of these poco specific things in ofSimpleApp.h that were sort of hard to understand…

I am still super freaked out that you can hypothetically have nothing in testApp.h/testApp.cpp and have stuff on screen. That’s pretty cool, but I have to admit it kind of weirds me out too - from a maintenance and debugging standpoint. it seems almost too magical in a way to have it happen in the constructor of the baseClass. it’s freaking smart btw :slight_smile:

we are happy to introduce poco and events listeners in, but I’m a personally hoping for something along the lines of

ofAddListener(…, OF_EVENT_SETUP);
ofRemoveListener(…, OF_EVENT_SETUP);

with the delegates happening behind the scenes. that’s a bit more work, but I think it’d make for cleaner code (well cleaner in the sense of reading and understand what’s happening). I like the idea of being able to tap into specific functions, like keyPressed but not keyReleased.

anyway, I love where this is heading and this stuff is mega powerful.

about ofVideoGrabber, etc, I would argue not to go this route - we have tried to make our classes as much as possible not use each other so that others can easily rip them out and reuse them, and I would worry about events making it much harder and less transparent how things function. that’s my 2c, but again, seeing this stuff in action is a better sense of how useful it is.

thanks so much for experimenting and showing different approaches. it’s really cool stuff –

zach

oh yeah, I like that.
Let me throw some additions in as well …

Look Everybody, No Hands (Pointers)!

http://file.stefanix.net/of-v005-poco-e-…-atch-3.zip
-> copy files manually into ‘app’ and ‘sound’ of OF core.

Arturo’s idea is cool because it eliminates the OFAPtr stuff. For both the ofRunApp and the ofSoundStreamSetup we don’t have to deal with pointers anymore. So, we are totally pointer-free in the user code! Also the app runner code (the stuff that is in openFrameworks/app) is less entangled with other code. With the attached patch there is no reference to ofSimpleApp in the app runner code at all.

I haven’t really looked into much whether this feels too implicit. One way to make things more explicit would be to move the inheritance from the listeners straight to the testApp. On the other hand registering all the standard event handlers in each app seems a bit excessive. For more custom events I am pretty much sold, though, to use addListener/removeListener.

To the summary of changes:

  • I got rid of the ofApp class (was kind of messy anyways, which also
    means no more assignEventHandlers() ). ofSimpleApp now inherits from
    all the new Listener classes. Need an app base class without audio,
    just leave out the inheritance from ofAudioListener. Need an app that
    reacts to networking events simply add ofxNetListener to the
    inheritance list. Or need multitouch events, add ofxTouchListener.
  
  
class ofSimpleApp : public ofSetupListener, public ofUpdateListener,  
                    public ofDrawListener, public ofKeyListener,  
                    public ofMouseListener, public ofAudioListener {  
  
[...]  
  
}  
  

  • In main, create the app on the stack. ofSimpleApp knows how to hook itself up to the event managers.
  
  
    testApp app = testApp();  
    ofRunApp();  
  

  • For sound stream apps
  
  
ofSoundStreamSetup(2,0, this, sampleRate,256, 4);  
becomes:  
ofSoundStreamSetup(2,0, sampleRate,256, 4);  
  

Happy Hacking,

cool !

for me personally it still feels a bit too implicit – I’d really love it to be clear what is hooked up and how – not in testApp, but in the other folks that do hook in. I don’t think it’s so bad to have one massive hook up in their constructor:

  
  
ofAddEventListener ( myMousePressed, OF_EVENT_MOUSE_PRESSED)  
ofAddEventListener ( myMouseReleased, OF_EVENT_MOUSE_RELEASED)  
...  
  

also because this would

(a) make it clear in the code right away that they are doing some ofEvent specific binging
(b) allow more flexibility in terms of different names (ie mousePressed can be called whatever you want)
© allow classes to turn on or off different listeners
(d) allow you to see really clearly which listeners are turned on or implemented.
(e) give you a block of code to comment out the listeners really easily

the problem I can see with extending base classes isnot being able to see clearly what each base class listeners their are - and that it’d be confusing code to know how it works from an outsider / beginners perspective.

but anyway, it looks mad powerful ! Seriously the base class stuff is pretty genius. It seems like it’s getting cleaner and cleaner :slight_smile: nice to not have pointers now too!

can’t wait to give it a spin.

take care!
zach

Hi

thanks for the wows :slight_smile: i work/teach with j2ee frameworks like struts, spring… and this kind of stuff is really frequent there.

Zach i’m totally with you that this solution is not very good as this kind of inheritance makes code really dependent on the framework and mantainance/debugging more dificult.

But for getting rid of complex pointer parameters in the ofAddListener / ofRemoveListener functions I think that some kind of polymorphism is needed.

What about something like the java-event-model. We can define some base classes like the ones I posted but doesn’t have any behaviour, they just act like java interfaces.

Then the ofAddListener / ofRemoveListener functions could be defined like:

  
ofAddListener(ofListener * listener, eventType event)  

and inside it you can know the correct listener type from the eventType parameter and using dynamic_cast we can detect if the class is inheriting from the right listener and show an advice if not.

This would force to use always the same method names, but I don’t think standard naming is that bad, indeed it helps to understand other peoples code easier. An in the end you always have the original poco calls if you really need to use your own method names and no inheritance.

Then there’s also some kind of typeof mechanisms in gcc but i think it’s not c/c++ standard

I am trying to implement the ofAddEventListener function. We actually need a bunch of information to hook up the listener in poco:

  • method to be called
  • reference to the method’s object (typically ‘this’)
  • type of the reference ( typically ‘testApp’)
  • type of the event object that is being passed to the listener

Basically the latter three need to be defined in the OF_EVENT_MOUSE_PRESSED somehow. Not sure how to do this best. Some info is here:
http://www.parashift.com/c+±faq-lite/p-…-mbers.html

Alternatively we could do this:

  • Each type of event has its own event object (ofKeyEvent becomes ofKeyPressedEvent, ofKeyReleasedEvent )
  • several addListener methods are defined in the event listener classes
  • based on the signature the right addListener is called
  
  
addListener( myKeyPressed );  
  

ofKeyListener would implement the following methods for this particular event (constructor is empty):

  
  
addListener( void (ofKeyListener::*)(const void*, ofKeyPressedEvent&) method ) {  
    ofKeyPressedEventManager += Delegate<ofKeyListener, ofKeyPressedEvent >(this, &ofKeyListener::method);  
}  
  

The passed method type looks totally crazy … whats cool, based on the singnature of myKeyPressed, the right addListener is chosen from the base classes. (wahoo!) Then if we feel like making this look more explicit we can always pass in some dummy ofKeyReleasedEvent as the second argument of addListener. This would also throw a compile time error in case of trying to hook up the wrong listener.

I have tried out the above idea where we would have multiple addListener methods with different signatures. Well it works but there is a flaw. Explanation follows. For this reason the Java event model is probably the closest viable path. This entails fixed names for listener methods and different names for methods that register listeners. I personally prefer fixed names. Also, poco will not even allow you to register two methods from one object with the same event manager anyways. And third, passing method pointers in C++ always looks complicated, afaik. You cannot just pass ‘myKeyPressed’ but you have to say ‘&testApp::myKeyPressed’.

To the flaw for those interested: Basically when trying to registering a key pressed listener method from testApp the signature of the method pointer is:

  
  
void (testApp::*)(const void*, ofKeyPressedEvent&)  
  

The problem is ofKeyListener has no idea about the ‘testApp’ type. It would work by first casting the method pointer to:

  
  
void (ofKeyListener::*)(const void*, ofKeyPressedEvent&)  
  

But this super ugly cast would have to be in the user code since passing a void* and casting in ofKeyListener is illegal when it comes to method pointers.

I’ve done an example implementation of the java model i described before and adapted the previous example to work with it:

the app folder: stefan, your last changes are not in there so ofApp yet uses poco directly:
http://65.111.166.199/openframeworks/ofAppPoco.zip

the example:
http://65.111.166.199/openframeworks/eventsListenerExample.zip

There’s an ofAddListener and an ofRemoveListener. The example shows how they work by registering events in the mouseEventListener example or in testApp. It also removes/add mouse moved event when mouse button is pressed.

I think that apart from having code independence with poco, the syntax of poco is the cleanest way of registering events in a language like c++ without using inheritance. It’s exactly the same as that used in c++/c# .net. And I suppose that using templates is the less complex way of adapting a method to work with different classes without using polimorphism.

Also the current naming for poco events as eventManagers and eventArgs as events can be confusing, I changed it so both of them are named the same as in poco and called the module that does registering/unregistering eventManager, but if you think it’s better as it was I can rename them again.

There are some events that directly use Poco::EventArgs, I think we should redefine them as ofEventArgs or something similar so just the ofEventModel files have direct dependencies with poco.

hey nice! what’s great here is it’s clear how events are being turned on, and the dynamic cast thing gives you a warning when you use it wrong (instead of doing really bad stuff). seems really clean and java folks will understand it really well. Also, from a maitenance point of view, future OF code will be clear.

stefan, thanks so much for the info – it’s a much harder problem then it looks at first glance. I’ve just spent my way through a few c++ event tutorials and I can start to appreciate stuff like c# :slight_smile: I am learning a ton just to keep up with you guys. thanks so much both of you – it’s gonna be a great addition to OF.

take care,
zach

With some guessing I figured that should be:
http://65.111.166.199/openframeworks/ev-…-xample.zip

The dynamic cast is sick. I wonder though how easy it is with this ofAddListener approach to add new events. You know, how do you create a ofSimpleApp equivalent that does networking events, etc. It seems to me that by having the ofAddListener as you suggested you would have to modify core code in your ofEventManager.h and ofEventModel.h.

I would be happy to be wrong about this.

EDIT: I guess one way would be that extensions have their own version of adding events:

  • ofxNetAddListener(…)
  • ofxNetEventModel.h
  • etc

I tried to merge arturo’s changed with mine when I noticed that using a function (as opposed to a method) to register events is a bit awkward. Internally it introduces a lot of unnecessary complexity (diamond inheritance, dynamic_casting, lots of files, enums, long switch sections, ) that makes it hard to adopt this event model for addons. In the user code it also adds some complexity ( pass by address with & )…

…anyways, when I tried to hook it all up a function did not make sense anymore. I changed the event registration mechanism along these lines:

From:
ofAddListener(&mouseListener,OF_DRAW_EVENT);

To:
mouseListener.listenToDrawEvents();

… and all of the diamond inheritance, dynamic_casting, 3 extra files, enums, long switch sections, went away. Also the implementation code is grouped nicely. Event managers and event args are in one file. Listener and registering/unregistering is in another file. Also, the compile gives really nice feedback for almost any way this can be misused.

Here is the complete patch including arturo’s example:
http://file.stefanix.net/of-v005-poco-e-…-atch-4.zip

(manually copy files from ‘app’ and ‘sound’)
(I haven’t adopted arturo’s new naming convention yet)

Hi stefan

From my experience, going that way is really dangerous :). Seriously, I remember doing that for some projects, at first it seems really ordered, but you can easily end with the functionality of a class layered across the inheritance what makes it really hard to understand and mantain/debug.

Also the registering/unregistering functionality gets scattered among several files/classes.

About the issues you point out, diamond inheritance can be avoided just declaring the event parameter as void* and getting rid of the ofListener class. The enums can be changed by defines, the dynamic casting is only to detect the problem and give an advice but you can use old casting.

Also we can create a diferent function for each kind of listener which should eliminate most of the problems you point out.

I was thinking that perhaps something like ofCreateEvent(char * eventName, ofEventArgs* eventArgs) can be done and then use the ofAddListener, ofRemoveListener functions. With your solution you are at first sight limited to the original events.

But this is really interesting, let’s keep trying some ideas…

Hey

just an idea about why we should separate the event registration in a diferent module than the listeners:

We can also add a method like ofCastEvent and use a generic ofEventArgs so the only files that has dependencies with poco are ofEventModel and ofEventManager

This will give great independence from poco, so you can substitute it if its needed with any similar library just by modifying the ofEventManager/Model.

For example, you can create a new eventManager that instead of using poco events, broadcasts osc messages over the network. You can theoretically convert any OF app into a distributed one without touching a single line of code apart from the includes to the new manager/model.