Python - Use threading.Condition to wait for condition or timeout without restarting timeouts on notify_all()

Viewed 42

Example class for illustration, please see comments for relevant info and questions

import threading

class ThreadedAccess:
    def __init__(self) -> None:
        self.stuff: list[str] = []
        self.updateEvent: threading.Condition = threading.Condition()
        self.timeout: float = 10

    # The problem with this approach is that the timeout will restart if this thread's condition 
    # is still not met after a notify_all() is called on the threading.Condition object
    # The desired behavior is that each thread times out absolutely after the elapsed time,
    # whether it has been notified or not
    def check_stuff_available(self, thing: str) -> bool:
        with self.updateEvent:
            while thing not in self.stuff:
                if not self.updateEvent.wait(self.timeout):
                    return False # timed out waiting for thing to be present, return false availability
            return True

    # I do not know if wait_for restarts the timeout on each notify_all() call
    def check_stuff_available_using_wait_for(self, thing:str) -> bool:
        with self.updateEvent:
            return self.updateEvent.wait_for(lambda: thing in self.stuff, self.timeout)
    

    def add_stuff(self, thing: str) -> None:
        with self.updateEvent:
            self.stuff.append(thing)
            self.updateEvent.notify_all()

    # This seems like the most obvious solution, but I'm wondering if there's a cleaner way to do it
    def check_stuff_with_manual_timeout(self, thing: str) -> bool:
        with self.updateEvent:
            startTime = time.time()
            currentTime = startTime
            while thing not in self.stuff and (currentTime - startTime) < self.timeout:
                if not self.updateEvent.wait(self.timeout - (currentTime - startTime)):
                    return False
                currentTime = time.time()
            return thing in self.stuff

Does wait_for resume or restart the timeout if its condition is not met after a notify_all()? Is the only way to get the desired behavior to track the time manually relative to system clock just before waiting?

0 Answers
Related