threading/events questions

Tim Peters tim_one at email.msn.com
Tue Apr 27 11:51:43 EDT 1999


[Chris...]
>   After experimenting with the modules thread and threading I have
> some open questions.  I've written the famous ping-pong program
> ------------------------------------------------------------------
> from Threading import *
> from time import sleep
>
> Quit = Event()
>
> def f(t, msg):
>     print msg
>     Quit.wait(t)
>     if Quit.isSet():
>         return
>     f(t, msg)

Note that recursion is inappropriate here:  Python does not optimize tail
calls, and so the thread stack keeps growing and growing.  Not what you want
for a long-running server <wink>.

> def run():
>     t1 = Thread(target=f, args=(10, 'ping'))
>     t2 = Thread(target=f, args=(5, '\tpong'))
>     t1.start()
>     t2.start()
>     sleep(60)
>     Quit.set()
> ------------------------------------------------------------------
> With that program, the threads are running for 60 seconds.  But, how
> can I stop one thread and not both?  I don't want to write an
> additional function doing exactly the same except dealing with a
> different Event.

Events are delicate, but if that's *all* you want to do just give f another
"early out" argument; e.g.,

def f(t, msg, earlyout):
    while 1:
        print msg
        Quit.wait(t)
        if Quit.isSet() or earlyout.isSet():
            return

def run():
    earlyout_t1 = Event()
    earlyout_t2 = Event()
    t1 = Thread(target=f, args=(10, 'ping', earlyout_t1))
    t2 = Thread(target=f, args=(5, '\tpong', earlyout_t2))
    t1.start()
    t2.start()
    sleep(30)
    earlyout_t2.set()
    sleep(30)
    Quit.set()

That stops t2 after 30 seconds but lets t1 run the full 60.  As your program
grows fancier, it would also be better to pass "Quit" as an argument rather
than rely on an increasingly nasty web of global vrbls.

>   My second problem is sending an event with a message.
> ChangeOutput = Event()
> and send the event ChangeOutput('something different than ping-pong')
> to one thread.  After receiving this message, the thread should change
> the recursive call to f(t, 'something different, than ping-pong').

Events can't be directed to a specific thread, nor can they carry
information beyond the "clear or set?" distinction.  I'm not clear enough on
exactly what it is you want to accomplish to suggest an alternative, though.

>   How can I wait for events (more than one)?

Unclear whether you want to wait for at least one, or for all.  If all:

e1.wait()
e2.wait()
e3.wait()
...

If at least one, you can poll in a busy loop:

    while not (e1.isSet() or e2.isSet() or ...):
        pass

or use a fancier synchronization mechanism; Events are really pretty feeble,
and you shouldn't expect to get fancy stuff done with them; Conditions are
more powerful.

> In the code above, I am just waiting for one event with a proper timeout.
> How can I react on the additional event ChangeOutput?

I got lost a few sentences back, so I'll shut up now <wink>.

the-problem-with-parallelism-is-that-it's-not-serial-ly y'rs  - tim






More information about the Python-list mailing list