I’m not sure if this is the right place to discuss internal implementation 
details, so apologies in advance if not…

Ivan and I have been going back and forth regarding some of the subtleties of 
how Tkinter and Tcl/Tk interact, which can come up particularly with regards to 
threads, but also in other ways. This is in the context of a reference doc 
update he’s proposed. It’s gotten me to pop my head into the code (_tkinter.c) 
several times. 

It’s a classic case of “who is in charge” when you try to merge two different 
event models with two different sets of constraints on them. To simplify, the 
Tkinter mainloop code is more or less in charge, calling out to Tcl to process 
one event (or return back if no events show up quickly enough). In the times 
when it’s not in the middle of a call to Tcl to process an event, it can also 
call into Tcl directly to run a command (e.g. turn the canvas item pink). 
Adding threads to the mix is another layer but still amounts to calling into 
Tcl in the right way at the right time. Tkinter needs to do a lot of clever 
things with locks, timeouts, etc. to make some of the magic happen.

It strikes me there’s another way to do this that might both simplify the 
Tkinter code and make it more robust, even in some of the weird and wacky ways 
that people are using it (despite being warned it’s not a good idea!).

Tcl’s event handling mechanism was updated in Tcl 7.5 (1996) at the time it was 
being moved from Unix-only to Mac and Windows. It explicitly provides 
mechanisms to deal with integrating with other event loops, and situations 
where either Tcl’s event loop is in charge (but can handle generated events 
from external code) or vice versa. The documentation can be found at 
http://www.tcl.tk/man/tcl8.6/TclLib/Notifier.htm

Tkinter can potentially make use of these facilities. Rather than the juggling 
act that Tkinter’s mainloop does now, it can just run Tcl’s event loop. Tkinter 
would also register itself with Tcl as an event source. This is a way that it 
can provide new “events” to the Tcl event loop. In this case, the “events” are 
really Tkinter calls that we want to send on to Tcl/Tk. Registering as an event 
source essentially means that Tcl will repeatedly call into Tkinter to ask “got 
anything new for me?”. if no Tkinter commands are pending, then the answer is 
no. If there is a Python command pending, an “event” can be added to the Tcl 
event queue. The event handler for that event would then call back into 
Tkinter, get the Tcl command, execute it, and pass the result back to Tkinter. 

The best part of this, at least as far as stability goes, is that Tcl controls 
the timing of the calls into Tkinter, so that it will only make them when it’s 
“safe” to do so, from a thread it expects to do so from, etc. Given that Tcl 
has the stricter restrictions on what can be called when and from where, this 
seems like a win. On the Tkinter side, it never has to worry about if it’s safe 
to call into Tcl.

(The one exception to this is probably application startup, i.e. before we hit 
mainloop, where Tkinter would just call directly into Tcl. It may be a 
reasonable restriction to say that you have to make Tkinter calls from the 
originating thread if they’re made before you hit mainloop).

To me this appears like it should be feasible. Any thoughts?

Mark



_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss@python.org
https://mail.python.org/mailman/listinfo/tkinter-discuss

Reply via email to