Comment

Comment by waddlesplash

You are correct that deadlocks can be caused by signals occurring before the wait starts, and thus some sort of mechanism to ensure this does not happen is needed, but I explained as much in the article. The point of this API is that the atomic lock-switch is not restricted to just locks; and further, in some situations, no lock-switch is needed at all.

The former is simple enough, and directly equivalent to what FreeBSD's API allows you to do (and what Haiku's API provides as "convenience methods", as the article notes), and is "atomic" -- it just pushes the atomicity up a level and lets the programmer control it more directly:

    ConditionVariableEntry entry;
    gSomeConditionVariable->Add(&entry);
    mutex_unlock(&someLock);
    /* (I could unlock more locks here, if needed, I'm not limited to 1) */
    entry.Wait();
    mutex_lock(&someLock);
The latter case is the more interesting and unique one, and the article references one place it is actually used in practice (team/process creation), though it doesn't give a pseudocode example, so let me try to give one here:

    ConditionVariableEntry entry;
    someLongRunningOperation.conditionVariable->Add(&entry);
    someLongRunningOperation.start();
    /* (I can do whatever I want here, no need to Wait immediately) */
    entry.Wait();
Since this "long-running operation" is not even started until after the local Entry has been Add'ed to the Variable, there's no possible way for this operation to complete and signal before we have started 'waiting' (because, even if the Wait() call is at the end, it's the Add() call that counts.)

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton