Hacker News new | ask | show | jobs
by exDM69 3665 days ago
Since most platforms defer condition signalling to mutex unlocks, the way the code is now written will cause more spurious wakeups and context switching than necessary.

The pathological case in scheduling goes like this:

    1. Reader A enters pop_front on an empty queue, goes to wait on the condition variable
    2. Writer W enters push_back, adds an element to list and releases mutex and get pre-empted (on line 25 first example)
    3. Reader B enters pop_front, sees queue not empty, pops element and leaves
    4. Writer W signals condition, wakes up Reader A
    5. Reader A wakes up but the queue is empty, goes back to sleep causing unnecessary context switch and trashing the TLB
The code is "correct" either way, but it's now optimized for the rare platforms that have a badly implemented condition variable.

I would say it's usually better to signal your condition variables with mutexes locked unless you know you're running on a platform with flaky condition variables. Easier to guarantee correctness and avoid spurious wakeups that way.

related note: cppreference.com is a terrible resource. It was worse 10 years ago, but it's not improved much. I would not trust the weasel wording ("some implementations" etc) in the link you posted, what it says about pthreads contradicts the pthread man pages (that encourage signal while holding lock)

1 comments

From what I've seen (YMMV), chances of it happening are MUCH smaller than chances of getting context switch under the lock (with lots of threads running into this lock and having their own context switches), because of spending more time under the lock than it is really necessary (and ANY call, especially kernel call at 300+ clocks, is a LOT of time). Strictly speaking, it needs to be measured, but until that point - I'm keeping my mutex locks as small as possible.