From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Tue, 27 Apr 1999 12:01:22 -0400 (EDT)
Subject: threading/events questions
In-Reply-To: <3725a47f.96308574@scout>
References: <3725a47f.96308574@scout>
Message-ID: <14117.54695.658787.508940@bitdiddle.cnri.reston.va.us>
Content-Length: 2934
X-UID: 460                                                  

>>>>> "C" == Chris  <sca at isogmbh.de> writes:

  C> Hello...  After experimenting with the modules thread and
  C> threading I have some open questions.  I've written the famous
  C> ping-pong program.

I'm not familiar with the ping-pong problem in general.  I wonder if
the code you posted is doing exactly what you intended.  The event
you're using could be used to allow communicate/synchronization
between the threads, but instead it's being used to sleep; the
Quit.wait() call only returns after the timeout period.  So you could
just as easily call sleep:

def f(t, msg):
    print msg
##    Quit.wait(t)
##    if Quit.isSet():
##        return
    time.sleep(t)
    f(t, msg)

You could also replace the recursive function call with a loop:

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

  C> With that program, the threads are running for 60 seconds.  But,
  C> how can I stop one thread and not both?  I don't want to write an
  C> additional function doing exactly the same except dealing with a
  C> different Event.

You could make the event a parameter instead of a global variable:

def f(timeout, event, msg):
    print msg
    event.wait(timeout)
    if event.isSet():
        return
    f(timeout, event, msg)

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

Event objects don't have associated messages be default.  You would
need to create a new object that also had an associated message.

You could create an object that has the functionality you're
interested in and an associated event.  You could manage the two
separately, although it seems like you do less bookkeeping if the
object has the event as an instance variable.  Not sure if there are
pitfalls lurking...

import threading
class MessageHolder(threading._Event):
    def __init__(self, msg):
        threading._Event.__init__(self)
        self.msg = msg
    def set_msg(self, msg):
        self.msg = msg
        self.set()
    def get_msg(self):
        return self.msg

def f2(timeout, msg_obj):
    while 1:
        print msg_obj.get_msg()
        msg_obj.wait(timeout)
        if msg_obj.isSet():
            msg_obj.clear()

  C>   How can I wait for events (more than one)?  In the code above,
  C> I am just waiting for one event with a proper timeout.  How can I
  C> react on the additional event ChangeOutput?

Good question!  I don't have a good answer.  You might have some
arrangement with hierarchical events (or conditions), so that one
event is set only when one of the events under it is set.  So you can
wait on the upper event, and when it is set, check each of the
underlying events.

Jeremy




