Peter Dufault wrote:
> You said it was just wxpythonfoobar, and not "python" or "bitpim",
> that was broken. I thought you were right, and I think the new
> release bears you out. Until now I always wondered if it might not
> have been some minor threading issue in bitpim that would persist
> beyond the upgrade.
All the stack traces always pointed the finger firmly at wxPython.
I certainly understand your wariness and suspicion of threading
issues.
The previous major commercial program I worked on was a seriously
multi-threaded server program in Java. You have to architect and
implement those right, or get badly burnt.
Python has a simpler threading model. In particular there is a
global interpretter lock (GIL) and only one thread at a time will
be running Python code. Various C extensions then have the
ability to release and acquire the GIL. For example my C code
that reads from the USB port looks like this:
int res;
Py_BEGIN_ALLOW_THREADS
res=usb_bulk_read(dev, ep, bytesoutbuffer, *bytesoutbuffersize, timeout);
Py_END_ALLOW_THREADS
return;
So ultimately C extension code can actually execute concurrently
for anything that is between Py_{BEGIN,END}_ALLOW_THREADS.
However Python code does not execute concurrently. If
you started two threads doing this:
while True: pass
Then the Python interpretter would keep switching between them. No
matter how many CPUs you had, Python would use at most one with
each thread getting half the CPU time.
The thread switching boundary is a bytecode instruction.
That means that all operations at the bytecode level are
atomic, and the bytecode instructions are very high level.
Contrast that with Java where reading/writing to a long
(64 bit quantity) is not atomic, and you do have actual
multiple concurrent threads, and the thread switching
boundary is whatever the CPU accepts (typically a machine
instruction).
Given all that, I can't actually think of a way of corrupting
information/state in Python if I deliberately wanted to.
In Java it doesn't take much :-)
Additionally the wxPython/wxWidgets library is not thread safe
(by design). All GUI stuff must happen in one thread. If
you do not do so then things will come crashing down VERY
quickly.
Finally the threading is done very carefully. There are
exactly two threads (*). One thread does all the GUI
work and almost all the other work as well. The second
thread does the communication with the phone.
The communication between the threads is done using Python's
Queue.Queue object from one to two, and using wx.PostMessage
(a primitive designed for this in wxPython) from two to one.
Data ownership is transferred with the messages or a copy
is sent. In any event data/state can't be corrupted at
the C level because of the GIL, and if bad things were
being done by the code would result in a Python exception
in the worst case.
(*) There are actually more threads if you use BitFling.
So your thread paranoia would be appropriate for Java based
programs, very appropriate for C programs and really doesn't
apply for Python programs.
About the only threading issue with Python programs that
people have is that pure Python code won't scale to
multiple CPUs. The solution is either to use C extension
libraries with Py_{BEGIN,END}_ALLOW_THREADS or multiple
processes.
Roger
|