On Mon, Mar 25, 2013 at 8:02 AM, Mark Evenson <evenson@panix.com> wrote:
(test condition-variable (setf *shared* 0) (let ((num-procs 100)) (dotimes (i num-procs) (make-thread (compile nil `(lambda () (with-lock-held (*lock*) (loop until (= ,i *shared*) do (condition-wait *condition-variable* *lock*)) (incf *shared*)) (condition-notify *condition-variable*))))) (with-lock-held (*lock*) (loop until (= num-procs *shared*) do (condition-wait *condition-variable* *lock*))) (is (equal num-procs *shared*))))
The test suggests a cute idea, whether or not the original author intended it. Typically a condition variable is used for producing/consuming, but in this case it could be used for something like a game of "hot potato". The bug is that the potato is not getting passed around. The fix is to move the existing condition-notify inside the lock and to insert a condition-notify before each condition-wait call. In effect each participant in the game is both a consumer and a producer -- a relay for the potato until the participant is "it". However even with that fix the test seems irredeemable because I don't think a cascade of condition-notifies is required to reach all waiting threads, i.e., all participants aren't guaranteed to get the potato. The potato could perpetually bounce between two participants, for example. At least there's no apparent need for a Lisp implementation to come with a "potato guarantee".