From: "rklemme (Robert Klemme)" Date: 2012-09-30T03:44:43+09:00 Subject: [ruby-core:47744] [ruby-trunk - Bug #7086] ConditionVariable#wait has meaningless return value Issue #7086 has been updated by rklemme (Robert Klemme). kosaki (Motohiro KOSAKI) wrote: > I think Java API spec is crazy and buggy. :-) > And then, no timeout doesn't mean the condition become true and an API user always have to ignore the return value and check > his own condition again. There is some truth in what you write. In the usual case you certainly need to check your condition. But I think nevertheless that the Java way is not crazy. > Moreover, we have one another mess. When cv#signal was not only fired but also timeout occur, some OS return timeout occur and > other return cv#signal received. Both POSIX and Java permit such platform dependency. then, you must not trust the return value. I disagree that the named facts make the return value useless. See below. > I'm hesitate to implement it because it seems bring a lot of trouble than worth. We certainly need to give a bit more thought to this. So, the condition needs to be checked to be sure it is met. But: in case of timeout you can do a quick exit of the loop if #wait has a proper return value. The usage pattern would look like this: def do_whatever(timeout) target = Time.now + timeout lock.synchronize do until condition cv.wait(target - Time.now) or return :fail end whatever end :ok end The race condition between spurious wakeup, timeout and signaling is really irrelevant. The reason is this: if any two of them happen at approximately the same time it doesn't matter whether one of them is a few microseconds earlier or the implementation prefers one of them. The outcome (i.e. return value) is random for the observer anyway. You also cannot create a test which would verify certain behavior reliably because you cannot control execution order down to the nanosecond. But: if the timeout is detected it is extremely useful to indicate that fact via the return value. Otherwise the idiom shown above would become more complex: def do_whatever(timeout) target = Time.now + timeout lock.synchronize do until condition sec = target - Time.now return :fail if sec <= 0 cv.wait sec end whatever end :ok end If we allow instances of Time and DateTime as "timeout" argument to #wait things become even simpler: def do_whatever(timeout) target = Time.now + timeout lock.synchronize do until condition cv.wait target or return :fail end whatever end :ok end It would also be nice if MonitorMixin::ConditionVariable allowed for a timeout argument to #wait_until and #wait_while. Then we could remove the loop altogether yet retain the time limitation. :-) ---------------------------------------- Bug #7086: ConditionVariable#wait has meaningless return value https://bugs.ruby-lang.org/issues/7086#change-29798 Author: rklemme (Robert Klemme) Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: ruby 1.9.3p194 (2012-04-20) [i686-linux] I consider this an API bug: when invoked with a timeout value the caller cannot distinguish from the return value whether the condition has been signaled or the time has run out. Consider how Java does it: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html#await(long,%20java.util.concurrent.TimeUnit) and http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html#awaitUntil(java.util.Date) There's another issue exhibited through the script but I will create a separate ticket for this. -- http://bugs.ruby-lang.org/