
Peter Dimov wrote:
These races typically don't occur in CV designs since a thread never waits for a CV, it waits for a condition in a while loop
lock lk( mx );
while( !condition ) { cv.wait( lk ); }
and it's checking the condition under the protection of mx. If the thread that modifies 'condition' also does so under the protection of mx, there are no races.
You can't use a condition variable as a signalling primitive such as an event, because it maintains no state and keeps no memory of the notify/broadcast calls. So you need to keep an external predicate.
Is there a "reasonable" use case where a CV will not be used as you described (I mean, in a 'while' loop)? If there aren't any, then why wouldn't the CV interface be changed to do the while loop itself: template <typename Lock, typename Pred> void condition::wait(Lock &lock, Pred while_cond) { while (while_cond) { old_wait(lock); } } or something similar. Does that make sense? Yuval