Understanding PyEval_InitThreads

Robin Becker robin at jessikat.fsnet.co.uk
Thu Nov 21 05:55:13 EST 2002


In article <1037851388.29783 at yasure>, Donn Cave <donn at drizzle.com>
writes
>Quoth hansgeunsmeyer at earthlink.net (hg):
>...
>| As far as I understand it, it doesn't really matter _what_ the thread
>| state is that you swap into the current state before you do the
>| callback, as long as it is _some_ valid thread state (not NULL). So,
>| before you do the callback, at any moment when you're in the main
>| Python thread, you could store a pointer to the then current
>| threadstate.
>
>Why are there multiple thread states, then?  If we might as well just
>use the existing state of any thread, it seems like we are put to a
>lot of trouble to hunt one up.
>
>       Donn Cave, donn at drizzle.com

I guess we're talking cross purposes somewhat. There are different types
of call back, but consider only two kinds synchronous and asynchronous. 

I believe for the synchronous case we can argue that in a multithread
environment the callback should not be allowed to run in a different
thread. 

On windows at least Thomas' test_enumwindows.py can be easily extended
to multithread and the results indicate that ctypes is preserving the
thread correctly in this case. (see test code below)

The problem then is that Don's more general (presumably asynchronous)
case is not obviously supported.  I assume that the callback wrapper
embeds a threadstate somehow, but there's no way to set it to 'any'.

####### hacked to use multiple threads
# from Paul Moore via comp.lang.python
import thread, time
from ctypes import windll, CFunction, c_string
user32 = windll.user32

mutex = thread.allocate_lock()
count = 0

class EnumWindowsProc(CFunction):
    _types_ = "ii"
    _stdcall_ = 1

def DisplayWindow(hwnd, lparam, where=None):
    title = c_string('\000' * 256)
    user32.GetWindowTextA(hwnd, title, 255)
    num = thread.get_ident()
    time.sleep(0.000001)        # Let other threads run
    print >>where, "Thread%d: hwnd=%08x title=%s" % (num,hwnd, repr(title.value))
    print "Thread%d: hwnd=%08x title=%s" % (num,hwnd, repr(title.value))

def run(num=0):
    where = open('/tmp/test_enumwindows_out_%d.txt' % num,'w')
    user32.EnumWindows(EnumWindowsProc(lambda x,y,where=where: DisplayWindow(x,y,where)), 0)
    mutex.acquire()
    global count
    count += 1
    mutex.release()
    print 'Thread%d num=%d finished!' % (thread.get_ident(), num)

N=5
for num in xrange(N):
    thread.start_new_thread(run,(num,))

#spin wait
while 1:
    if mutex.acquire(0):
        if count==N:
            print 'Done!'
            mutex.release()
            break
        mutex.release()
    time.sleep(0.001)       # Let other threads run

-- 
Robin Becker



More information about the Python-list mailing list