Search code examples
mutexsleepcondition-variable

What condition variables can do that unlock+yield cannot?


In POSIX, there's the requirement that when a wait is called on a condition variable and a mutex, the 2 operations - unlocking the mutex and blocking the thread, be atomically performed, in such way that any broadcast/signal should take effect as if they happened after blocking. I suppose there should be equivalent requirements on C11, C++ condition variables as well, and I won't go on to do a verbose enumeration.

However, in some system (such as many people's nostalgia WinXP), there wasn't a condition variable mechanism. Instead, they have to perform a unlock+yield to achieve similar (same?) effect. And this works, because even if the broadcast/signal occured in-between the unlock and yield, when the thread is re-scheduled, its observable behavior is the same as if the wake occured after the block. WinXP supported mutex, and it had an SleepEx function that can work like an yield.

So it begs the question: What condition variables can do, that unlock+yield cannot?


In response to the comment: I use WinXP as an example because it happens to be one that supported mutex but not condvar, and the fact that it's one generation's memory. Of course, we assume correctness and reasonable performance, and the question doesn't specifically ask Windows and it asks any implementation in general.


Solution

  • CVs can do timed wait, while you cannot control when you wake up from an yield.

    CVs in the POSIX standard can wait until an absolute point in time passes. The reason it's not relative is that

    1. if you want to wait for an absolute time
    2. you have to do the math backwards to calculate a relative time, and
    3. if the thread is preempted between the calculation and the CV wait,
    4. the actual wake up could be delayed.