[Python-Dev] release candidate rules and timeit API question

Skip Montanaro skip@pobox.com
Tue, 1 Jul 2003 08:19:23 -0500


    Skip>     import time
    Skip>     class Timeout(Exception): pass
    Skip> 
    Skip>     def await_condition(predicate, timeout):
    Skip>         delay = 0.0005
    Skip>         endtime = time.time() + timeout
    Skip>         while True:
    Skip>             if predicate():
    Skip>                 return
    Skip>             remaining = endtime - time.time()
    Skip>             if remaining <= 0:          # time's up, predicate always failed
    Skip>                 raise Timeout
    Skip>             delay = min(delay * 2, remaining, .05)
    Skip>             time.sleep(delay)           # reduce CPU usage by using a sleep
    Skip> 

    Guido> I wonder if the right refactoring wouldn't be to add an acquire
    Guido> with timeout method to the built-in lock type?

In my case I use await_condition() to gracefully empty a Queue of database
connection objects at termination time.

    def check_conn_pool(self):
        try:
            conn = self.conn_pool.get(block=0)
        except Queue.Empty:
            pass
        else:
            conn.close()
            self._leftovers.append(conn)
        return len(self._leftovers) == self.poolsize

    ...

    def empty_conn_pool(self, poolname, maxwait):
        self._leftovers = []
        try:
            await_condition(self.check_conn_pool, maxwait)
        except Timeout:
            print "could only find", len(self._leftovers),
            print "connections for", poolname

It's a bit clunky, but I wouldn't be able to use an acquire() with a
timeout directly.  I'd need a Queue.get with a timeout as well.

Besides, wouldn't there be places where this progressive backoff would be
useful in non-threaded contexts?

Skip