[Tutor] A chat server in Python

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Mon, 12 Aug 2002 08:16:23 -0700 (PDT)


On Mon, 12 Aug 2002, Scot W. Stevenson wrote:

> Thank you for the code example! If I could bother you with a few
> questions...
>
> ============================
> from threading import *
> ============================
>
> The docs for the threading module say that it is safe to do this, but I
> remember being told by one of the books (can't find the reference right
> now, will dig if important) not to unless you're importing Tkinter. Is
> threading another exception, or has "from <module> import *" become less
> dangerous in Python 2.2, or was the original warning overdone?

Hmmm... I usually avoid using 'from <module> import *', but the
'threading' docs says that the module has been explicitely designed to
make 'from threading import *' safe.  Until otherwise, I'll believe the
docs.  *grin*

Hmmm!  Perhaps it might be good to look into the 'threading' module later
on, and see exactly what the module writer has done to make it 'from
<module> import *' safe.



> ============================
>     def _waitForShutdownOrNewMessages(self):
>         return self._events.get()
> ============================
>
> Is ease of maintainance the the reason not to put self._events.get()
> directly into the "while 1" loop?

I made that one-liner into a separate function for maintenance reasons: I
wanted to make sure it was clear, to someone reading the program, that
self._events.get() can pause for a long time.



> ============================
>        self._listeners_lock.acquire()
>        try:
>             listeners_copy = self._listeners[:]
>         finally:
>             self._listeners_lock.release()
>         for listener in listeners_copy:
>             self._tryToSendMessageToListener(msg, listener)
> ============================
>
> I'm not sure I understand the reason for the copy of self._listeners, or
> in other words, why this part isn't simply
>
> ---------------------------------------------------
> self._listeners_lock.acquire()
> try:
>     for listener in self._listeners:
>         self._tryToSendMessageToListener(msg, listener)
> finally:
>     self._listeners_lock.release()
> ----------------------------------------------------
>
> since if self._listeners() is empty, the for-loop wouldn't run, and I
> don't see anything that could change self._listeners.


I think I wasn't thinking clearly.  *grin*

Yes, that should be fixed;  your revised loop is simpler and has the same
meaning.


The comment I embedded in MessageRoom._tryToSendMessageToListener()
explains that:

'''
            ## Fixme: we should somehow a timeout here.  If a message
            ## can't get through within a certain period of time, we
            ## should assume the listener is just delinquent, and toss
            ## them out of the listeners list.  Very rough, but
            ## necessary if we don't want to deadlock waiting for any
            ## particular listener.
'''

I was worried about locking out the '_listeners' from further
modification, because sending messages might potentially take a long time.
Perhaps I should really implement the timeout instead, like the comment
says.  *grin*


Thank you for your feedback!