On Mon, Sep 9, 2013 at 3:44 PM, Gavin Lambert
On 9/09/2013 10:34 p.m., Quoth Thomas M:
Now the question: Is there a strong point pro or against releasing controllerLock before the notify_all-signal is sent? E.g. is there preference for the first or second variant as below (see placement of curly brackets!), or even a need for one to ensure correctness?
The normal problem, IIRC, is that notify_all() will only wake up those threads that are actually sleeping on the condition variable already. If you release the lock early, then another thread might enter the locked region, discover that the condition is false, and be about to sleep on the condition variable when the notify is triggered -- it then goes to sleep permanently because it missed the wakeup event.
You still have to guarantee that any data that needs to live in the critical section is covered by the mutex lock. You cannot change or check the condition outside the mutual exclusion region. That's a bad race. Note that this is not the same as holding the lock when notifying the condition variable.
// simplified code snippet begin - Variant 2 // notify_all is issued when controllerLock has already been released { boost::unique_lockboost::mutex controllerLock(someMutex); Continue = true; } someCondVar.notify_all(); // simplified code snippet end
Given that you are updating the condition within the mutex I believe that this is safe from the above issue. However it still may not be safe due to other factors -- for instance, if the memory containing someCondVar becomes eligible for deletion once the condition is true (which happens more often than you'd think, particularly when the condition includes some sort of termination flag/event) then variant 1 is still safe while variant 2 is not.
See my above comment.
In terms of efficiency, variant 2 is probably more efficient than variant 1 on a uniprocessor system, but on a multicore system they're probably about the same. (As on uniprocessor there is a chance that the notify could cause an immediate preemption, lockout, and switchback with variant 1, while on a multicore the notifying thread should be able to continue to release the lock.)
My hunch is that you're right that it can be quite bad in the uniprocessor case, and that it's probably not as bad in the multiprocessor case. Brian