Right, and futexes also back condition variables in glibc.
And mutexes too!
I prefer the modern nutex construct
Probably atomic increment / decrement + condition_variable. Just check if you hit 0 on decrement to notify waiters (or return if you are the waiter).
Well now that sounds like a semaphore!
Almost certainly. Condition variables are very complicated internally. On Linux, a latch could be backed by a futex with very little code.
What is the source of the complexity inside condition variables? Reading the glibc sources, the main problem seems to be ensuring that signals are delivered properly?
Yes, atomic unlock + wait is the complex bit. Prior to Vista, Windows did not have a CV primitive. Existing emulations used multiple kernel objects and their correctness was difficult to verify. Performance also suffered.
I think Vista implemented keyed synchronization objects (i.e. a flavour of futexes) which have similar edge triggered semantics as CVs.
It's possible to implement very simple condition variables. The tricky part is preventing correct but inefficient behaviours like stampeding herds.
When implementing posix semantics there are a lot of nasty corner cases, especially with dealing with fairnes, graceful destruction, correct handling of wait generations and probably more that I'm missing.
I would never attempt to implement a full condvar.
Typical implementations use std::atomic or a variation of it (further stripped version of it).