A helper template function to wait for a Win32 condition variable in a loop


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 Wait­On­Address 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::condition_variable::wait method which takes a predicate. If the predicate returns 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 Wait­On­Address because the loop is very straightforward. It may not be much of a benefit over just writing the loop out manually.

Comments (5)
  1. kantos says:

    Sadly the C++ implementation of std::condition_variable in the 15.* toolset is broken so if you want it to work correctly you’ll need to use the WIN32 version until that’s fixed in a breaking release.

    1. Bonus sadness is that the Win32 condition variable does not meet all the requirements of the C++ standard condition variable, so the runtime folks can’t just use it directly.

      1. Yuhong Bao says:

        I wonder why SignalObjectAndWaitMultiple was never created.

        1. JAS says:

          I wonder when there is going to be a serious effort to use coroutines to spiritually break out of Kernel Land. You can have faster, more advanced versions of all of these constructs.

          1. kantos says:

            The next version of the Windows SDK contains the CPP/WinRT components that support (and encourage) co-routines. Having already used them for some sockets code it was an absolute dream.

Comments are closed.

Skip to main content