On Tue, 30 Nov 2010 13:27:13 -0500, Vladimir Sedach said:
- At least one implementation (SBCL) requires that the lock on which
condition-wait is called is to be held by the thread that calls condition-notify on the corresponding CV. This should be mentioned in the documentation as a requirement.
Yes, this is a standard, but ill-documented, requirement for condition variables. The lock is needed to synchronize the notify with the change to the underlying data in the application.
At least on Clozure, B-T implements condition-wait/notify with semaphores, so this appears to work fine, even though on other implementations it might lead to race conditions.
OK, I see what you mean -- the implementation of condition-notify might not be thread safe within itself unless the lock is held.
I was referring to a different problem though. If you call condition-notify without holding the lock, then you can lose notifications, i.e. condition-wait might never wake up.
A typical use of condition-wait is like this:
(defun wait-for-it () (with-lock-held (lock) (loop (when (application-state-says-ready-p) (return)) ;; ** (condition-wait cv lock))))
and the corresponding use of condition-notify should be like this:
(defun provide-it () (with-lock-held (lock) (setf (application-state-says-ready-p) t) (condition-notify cv)))
You must use with-lock-held to change the application state and notify atomically w.r.t. the call to application-state-says-ready-p and condition-wait. This is because, at least according to the pthreads definition, condition variables have no memory of calls to notify that occurred when noone was waiting. If provide-it can run (in another thread) at the point labelled ** in wait-for-it, then the notify will be lost. The lock prevents provide-it from doing that.