[Python-Dev] release candidate rules and timeit API question (original) (raw)

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