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