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

Gabriel Rossetti gabriel.rossetti at arimaz.com
Fri Jul 17 02:12:38 EDT 2009


Maxim Khitrov wrote:
> 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
>   

Thank you, I will try that. I am coding for Linux, Mac & Windows (and 
any POSIX platform, but right now I support only those three).

Gabriel



More information about the Python-list mailing list