On Sat, Jan 28, 2012 at 4:10 PM, Jerzy Karczmarczuk <jerzy.karczmarczuk@unicaen.fr> wrote:
Ben Root, about my example in which an infinite callback loop overflows :
So, where is your terminating condition?  Of course it will continuously call itself if you have nothing to stop it.  Protect that call to "process" with some sort of if-statement and use "evt" to carry some sort of state that can be tested in that if-statement.

For example, I modified your example to use "evt" to carry an integer. 

The program then produces 10 random lines just fine when I press "Go".

Does that help clear up your problem?
No, I am afraid this not the solution, Ben. My program is distilled, the truth is more complicated, but I don't need any fixed termination condition, this is a simulation program which works continuously until some other button invalidates some variable, say "running" (or kills the window, etc.). It should go forever [of course the real program doesn't pollute the axes.lines memory, this is a non-issue].

Right, so you need to create your web of callbacks accordingly.  The callback registry is just simply a tool that we created for our use.  Keep in mind that your original question to this thread was "how do I fire events?".  I answered that question a while back.

The issue is that calling a callback from a callback is an abomination in general!

Then don't do it!  If it happens in mpl, it is rare and well controlled.
It should never happen. What SHOULD happen, and takes place in a "standard" event loop is that the last line of my procedure "line" is, equivalent [simplified] to

if running: push(line,queue)

The main loop works as follows:

while notempty(queue):

This "distributed loop" may run as long as you wish, no recursion overflow, and the possibility to stop it by another callback which assigns running=False.

Ok, but the callback registry is not an event loop.  It is just a callback registry.  The main-loops are in the respective GUI toolkits.
I repeat that I can in principle write it myself, under ion(), and never call show().
But mainloop() of ANY GUI backend does already everything that. But I don't know how to find the access to the event queue.

There is no event queue in the CallbackRegistry.  What we have done in the respective GUI backends is to link various GUI actions to calls to process().  The CallbackRegistry itself is GUI-neutral and heck, it doesn't even assume a GUI exists, which allows for us to still use the callback registry for other uses in non-interactive modes and headless modes.  Therefore, there is no mainloop, there is no event queue.
Under wx, when I write my own loop, there are shortcuts. app.Dispatch() processes the first event in the queue, or waits until something happens. Or I call app.ProcessPendingEvents().

My callbacks would call PostEvent(dest, event). The destination is a window. I did it some years ago, I don't remember the details, but Post did not block anything, returned immediately, and the callback containing it, as well. It is possible to Post an event also from another thread, and thus faking a Timer.

MPL was written with single-threadedness in mind.  There is an example of multi-processing and mpl, but I don't know how applicable it would be to you.  I will link it here in case it inspires someone:


If there were only the "virtual events", I wouldn't bother anybody. But I have to deal with all the mouse events as well as with the virtual ones. Cumbersome.

I also noticed that in the example you posted, you created your own callback registry.  Why didn't you use the existing one that comes with the figure canvas?

Quite honestly, I (and I suspect others) are not sure what you are asking of us.  You seem to be quite knowledgeable, but -- quite frankly -- all I see is you complaining about the problem.  Is there a bug that you wish to report?  Is there a fundamental design flaw in mpl that you wish to address?  Or are you confused about how to use the CallbackRegistry?

My only guess is that you were hoping that there was a GUI-neutral mainloop in mpl.  I am sorry to say that one doesn't exist in the manner you are speaking.  Each backend communicates with the GUI's mainloop as needed by the toolkit.  There is no abstracted API for this. Instead, very specific actions have been created for each backends.  All other actions (like object picking, changes in the axes and such) are GUI-neutral and do not need direct interaction with the mainloop (only a call to draw() when finished).

I really want to help you here, but I need you to be very clear about what you want and to exclude any extraneous "rants" you may have.

Ben Root

P.S. - Please keep this thread on-list.