Win32
condition variables
suffer from the problem of spurious wake-ups,
and you will usually wait on a condition variable in a loop.
It's easier than
the case of WaitOnAddress
because you hold a lock while checking the condition,
so you don't have to worry about race conditions against other threads.
(The idea is that anybody who wants to cause a change to the condition
needs to acquire the same lock.
Therefore holding the lock prevents the condition from changing.)
The C++ standard library contains an overload to
the std::
method
which takes a predicate.
If the predicate returns condition_
variable::
wait
false
,
then the wait
will loop back and wait some more.
Let's write that same helper function for Win32 condition variables.
template<typename TLambda> void SleepConditionVariableCSUntil( CONDITION_VARIABLE* conditionVariable, CRITICAL_SECTION* criticalSection, TLambda&& is_okay) { while (!is_okay()) { SleepConditionVariableCS(conditionVariable, criticalSection, INFINITE); } } template<typename TLambda> void SleepConditionVariableSharedSRWUntil( CONDITION_VARIABLE* conditionVariable, SRWLOCK* srwLock, TLambda&& is_okay) { while (!is_okay()) { SleepConditionVariableSRW(conditionVariable, srwLock, INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED); } } template<typename TLambda> void SleepConditionVariableExclusiveSRWUntil( CONDITION_VARIABLE* conditionVariable, SRWLOCK* srwLock, TLambda&& is_okay) { while (!is_okay()) { SleepConditionVariableSRW(conditionVariable, srwLock, INFINITE, 0); } }
I will admit that these helpers aren't as useful as the one
for WaitOnAddress
because the loop is very
straightforward.
It may not be much of a benefit over just writing the loop out manually.