Danny, I want to thank you for ruining my plans for a relaxing Saturday morning. As a thread newbie I killed several hours playing around with your code.
One thing I noticed is that sometimes the program would hang, which I figured was the Queue code blocking in the Ticket claim function. I used exception handling to deal with that situation cleanly. I then decided that it wasn't very nice of Starbucks to close after accepting my order without giving me my Latte, so I changed that part of the code to: def schedule(self,job): """Schedules a job and returns a "ticket" the user can later use to get the result.""" if self.acceptNew == True: outputQueue=Queue() self.queue.put((job,outputQueue)) return Ticket(outputQueue) else: print "Server not accepting any new requests." return None def scheduleShutdown(self): """Add a job that shuts the system down.""" print "Telling server to shut down" self.queue.put((Server._QUIT_NICELY,None)) def _jobLoop(self): """Continue looping through tasks.""" while True: print "Looping ... " (nextJob, outputQueue) = self.queue.get() if nextJob is server._QUIT_NOW: return if nextJob is server._QUIT_NICELY: self.acceptNew = False self.queue.put((Server._QUIT_NOW,None)) else: returnValue=self._doJob(nextJob) outputQueue.put(returnValue) I am 99.44% sure that this is thread safe, reasoning being: setting the acceptNew to False and adding the QUIT_NOW happens in the same thread so it is impossible for another job to get scheduled after the QUIT_NOW - so no thread will end up hanging... However, I would sleep a little better if you could reassure me that I am right, and would sleep even better if you could give me a method to test this. This kinda stuff looks tricky to test with standard unittest methodology.... Thanks again for the enligntenment all you guys bring to this awesome language. My bastardized code is below for reference. --Todd Maynard < [EMAIL PROTECTED] > [It is] best to confuse only one issue at a time. -- K&R ************************************** from threading import Thread from Queue import Queue,Empty class Ticket(object): """A small token we can use to claim our result.""" def __init__(self, q): self.q = q self.result = None self.done=False def claim(self): if not self.done: try: self.result=self.q.get(True,5) self.done=True except Empty: print "We lost the server!" self.result=None return self.result class Server(object): _QUIT_NOW=['Quit!'] _QUIT_NICELY=['Quit Nicely'] def __init__(self): """A queue will contain 2-tuples of (job, outputQueue) elements.""" self.queue=Queue() self.acceptNew=True def startServer(self): """Brings the server online.""" Thread(target=self._jobLoop).start() def schedule(self,job): """Schedules a job and returns a "ticket" the user can later use to get the result.""" if self.acceptNew == True: outputQueue=Queue() self.queue.put((job,outputQueue)) return Ticket(outputQueue) else: print "Server not accepting any new requests." return None def scheduleShutdown(self): """Add a job that shuts the system down.""" print "Telling server to shut down" self.queue.put((Server._QUIT_NICELY,None)) def _jobLoop(self): """Continue looping through tasks.""" while True: print "Looping ... " (nextJob, outputQueue) = self.queue.get() if nextJob is server._QUIT_NOW: return if nextJob is server._QUIT_NICELY: self.acceptNew = False self.queue.put((Server._QUIT_NOW,None)) else: returnValue=self._doJob(nextJob) outputQueue.put(returnValue) def _doJob(self,job): print "I'm doing " , job return job + job #Something to show that we are doing something def separateCaller(server): for i in range(1000,1004+1): print " -- separateCaller asks %d" % i ticket = server.schedule(str(i)) if ticket: print " -- separateCaller got %s" % ticket.claim() else: print " -- separateCaller couldn't get a ticket." if __name__=="__main__": server = Server() server.startServer() Thread(target=separateCaller, args=(server,)).start() result1=server.schedule("1") result2=server.schedule("2") result3=server.schedule("3") if result3: print "result3: %s" % result3.claim() else: print "result3: Couldn't get a ticket" if result2: print "result2: %s" % result2.claim() else: print "result2: Couldn't get a ticket" if result1: print "result1: %s" % result1.claim() else: print "result1: Couldn't get a ticket" server.scheduleShutdown() _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor