Mark Roseman <m...@markroseman.com> added the comment:

Hi Ivan, thanks for your detailed response. The approach you're suggesting 
("Since the sole offender is their threading model, the way is to show them how 
it's defective and work towards improving it.") is in the end not something I 
think is workable. 

Some historical context. Ousterhout had some specific ideas about how Tcl/Tk 
should be used, and that was well-reflected in his early control of the code 
base. He was certainly outspoken against threads. The main argument is that 
they're complicated if you don't know what you're doing, which included the 
"non-professional programmers" he considered the core audience. Enumerating how 
threads were used at the time, most of the uses could be handled (more simply) 
in other ways, such as event-driven and non-blocking timers and I/O (so what 
people today would refer to as the "node.js event model"). Threads (or separate 
communicating processes) were for long-running computations, things he always 
envisioned happening in C code (written by more "professional programmers"), 
not Tcl. His idea of how Tcl and C development would be split didn't match 
reality given faster machines, more memory, etc.

The second thing is that Tcl had multiple interpreters baked in pretty much 
from the beginning at the C level and exposed fairly early on (1996?) at the 
Tcl level, akin to PEP 554. Code isolation and resource management were the key 
motivators, but of course others followed. Creating and using Tcl interpreters 
was quick, lightweight (fast startup, low memory overhead, etc.) and easy. So 
in other words, the notion of multiple interpreters in Tcl vs. Python is 
completely different. I had one large application I built around that time that 
often ended up with hundreds of interpreters running.

Which brings me to threads and how they were added to the language. Your guess 
("My guess for the decision is it was the easiest way to migrate the code 
base") is incorrect. The idea of "one thread/one interpreter" was just not seen 
as a restriction, and was a very natural extension of what had come before. It 
fit the use cases well (AOLserver was another good example) and was still very 
understandable from the user level. Contrast with Python's GIL, etc. 

With that all said, there would be very little motivation to change the Tcl/Tk 
side to allow multiple threads to access one interpreter, because in terms of 
the API and programming model that Tcl/Tk advertises, it's simply not a 
problem. Keep in mind, the people working on the Tcl/Tk core are very smart 
programmers, know threads very well, etc., so it's not an issue of "they should 
know better" or "it's old." In other words, "show them how it's defective" is a 
non-starter. 

The other, more practical matter in pushing for changes in the Tcl/Tk core, is 
that there are a fairly small number of people working on it, very part-time. 
Almost all of them are most interested in the Tcl side, not Tk. Changes made in 
Tk most often amount to bug fixes because someone's running into something in 
their own work. Expecting large-scale changes to happen to Tk without some way 
to get dedicated new resources put into it is not realistic.

A final matter on the practical side. As you've carefully noted, certain Tcl/Tk 
calls now happen to work when called from different threads. Consider those a 
side-effect of present implementation, not a guarantee. Future core changes 
could change what can be called from different threads, making the situation 
better or worse. From the Tcl/Tk perspective, this is not a problem, and would 
not be caught by any testing, etc. Even if it were, it likely wouldn't be 
fixed. It would be considered an "abuse" of their API (I think correctly).

My suggestion, given the philosophical and practical mismatch, is that Tkinter 
move towards operating as if the API Tk provides is inviolate. In other words, 
all calls into a Tcl interpreter happen from the same thread that created the 
Tcl interpreter. Tkinter acts as a bridge between Python and Tcl/Tk. It should 
present an API to Python programs compatible with the Python threading model. 
It's Tkinter's responsibility to map that onto Tcl/Tk's single threaded API 
through whatever internal mechanism is necessary (i.e. pass everything to main 
thread, block caller thread until get response, etc.)

I'd go so far as to suggest that all the Tkapp 'call' code (i.e. every place 
that Tkinter calls Tcl_Eval) check what thread it's in, and issue a warning or 
error (at least for testing purposes) if it's being called from the "wrong" 
thread. Having this available in the near future would help people who are 
debugging what are fairly inexplicable problems now. 

The approach of making Tkinter responsible also has the advantage of dealing 
with far more Tcl/Tk versions and builds.

Given in practice that few people are really running into things, and that if 
they are, they know enough to be able to follow the instruction "all Tkinter 
calls from the same thread" for now, add the warnings/errors in via whatever 
"turn on debugging" mechanism makes sense. A future version of Python would 
include a fully thread-safe Tkinter that internally makes all Tcl/Tk calls from 
a single thread, as per above.

Sorry this is so incredibly long-winded. I hope the context at least is useful 
information.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue33479>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to