no return value for threading.Condition.wait(timeout)?

Maxim Khitrov mkhitrov at gmail.com
Thu Jul 16 17:22:32 EDT 2009


On Thu, Jul 16, 2009 at 5:00 PM, Carl Banks<pavlovevidence at gmail.com> wrote:
> On Jul 16, 8:12 am, Gabriel Rossetti <gabriel.rosse... at arimaz.com>
> wrote:
>> Hello everyone,
>>
>> I am using threading.Condition.wait(timeout) and was surprised to see
>> that there is no return value nor an exception when wait() is used w/ a
>> timeout. How am I supposed to know if it was notified or if it timed out?
>
> That's a good question.  Condition.wait seems to violate an invariant
> if it can return without having acquired the underlying lock.  And if
> it does the least it could do is to return a status so you know if you
> have to skeddadle.
>
> Workaround is to use the _is_owned() method of Condition to see if you
> are the owner of the condition, but this method is undocumented.
>
> cond = Condition()
> ...
> cond.acquire()
> while not ok_to_proceed():
>    cond.wait()
>    if not cond._is_owned():
>        # must've timed out
>        raise TimeOutException
> operate()
> cond.release()

You will always be the owner of the condition whether it times out or
your thread is notified. This doesn't solve the problem. As an aside,
the implementation of wait() is rather poor in any case; the sleep
function should not be used for the purpose of waiting for an event.

Depending on what platform you are using, I can offer two solutions.
The simplest one is to subclass Condition and override the wait
method. Just copy the code as it is, but modify the end of the
function to look like this:

                if not gotit:
                    if __debug__:
                        self._note("%s.wait(%s): timed out", self, timeout)
                    try:
                        self.__waiters.remove(waiter)
                    except ValueError:
                        pass
                    return False
                else:
                    if __debug__:
                        self._note("%s.wait(%s): got it", self, timeout)
                    return True

The two return statements will tell you whether you timed out ("if not
gotit" condition), or were notified ("else").

The better way to solve this and the other problem that I mentioned is
to use native OS events. This is what I had to do for a recent
project. I used pywin32 extension to completely rewrite Event,
Condition, and Timer classes to use a true event-based approach. In
the process of the rewrite I also modified some functionality, such as
returning True of False from wait().

Unfortunately, I'm not able to post this code right now, though I can
try and get permission to do so a bit later. If you are writing
software for Windows, then simply take a look at win32event module.
CreateEvent, SetEvent, ResetEvent, WaitForSingleObject are all the
Windows functions that you need to reimplement threading.Event. Using
the new event class you can implement a proper Condition.wait() method
(hint: use new events rather than locks to wait for notification).

If you are on Linux or BSD, I can't help you. I'm sure that there is
some equivalent functionality that you may be able to access using
ctypes. Exactly how to do it, however, is not something that I can
help you with right now.

- Max



More information about the Python-list mailing list