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::waitfalse, 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.
0 comments