multithreading and Tkinter

James Logajan JamesL at Lugoj.com
Mon Apr 1 18:46:50 EST 2002


martin at v.loewis.de (Martin v. Loewis) wrote:
> James Logajan <JamesL at Lugoj.com> writes:
> 
>> Has anyone ever tried using after_idle in a worker thread as a way to 
>> signal a Tkinter mainloop thread? I'm wondering if this proposal is 
>> really thread safe, since technically a worker thread is making a call
>> to Tk (even if it is nothing more than registering a callback) while
>> the mainloop thread may also be in the process of making calls to Tk. 
> 
> That cannot happen. _tkinter maintains a Tcl lock, guaranteeing that
> only one Python thread at any time calls into Tcl. 
> 
> You may wonder how you then can call in to Tcl while another Python
> thread calls tk_mainloop: tk_mainloop does not call a Tcl loop, but
> calls Tcl_DoOneEvent; if there was no event, it sleeps for 20ms
> (giving up the Tcl lock during that time). As a result, other threads
> can call into Tcl while Tcl is idle. If Tcl is active, those other
> threads will block in the Tcl lock.
> 
> People have been complaining about the presence of the Tcl lock, and
> the Sleep call (which means that there might be a 20ms delay between
> an event and the time when processing the even starts). You are
> encouraged to study the source of _tkinter.c, both to get trust in my
> statements, and to suggest improvements to the status quo.

Thanks! My old Linux system still has 1.5.2 so I took a quick look at the 
source code for that version. I _think_ I understand. When compiled 
_without_ thread support, mainloop loops over Tcl_DoOneEvent(0) calls, 
which will process one event or _wait_ for one to process before returning. 
But when compiled _with_ thread support it loops over 
Tcl_DoOneEvent(TCL_DONT_WAIT) calls, around which a Tcl lock has been 
placed (but the Python interpreter lock has been released). A 20ms window 
is opened where the Tcl and Python interpreter locks are opened to allow 
other threads to run unimpeded.

No good alternatives come to mind. I'm not sure if launching a thread 
dedicated to calling into Tcl would work (e.g. all threads making Tcl calls 
are really entering requests into a queue and signalling the dedicated Tcl 
thread to pick up and process their requests). I don't know anything about 
Tcl calls, which limits what I can suggest. It would also be a bit of work 
to implement in any case. I assume others with more knowledge of these 
things have considered all reasonable alternatives.



More information about the Python-list mailing list