I might be missing something, but I think that the handling of the sleeper state is wrong.
mutex is unlocked (state: unlocked)
A locks mutex (state: locked -> locked)
B attempts to lock mutex (state: locked -> sleeper)
C attempts to lock mutex (no changes)
A unlock mutex (state: sleeper -> unlocked), state was sleeper so notify_one B
B locks the mutex (state: unlocked ->locked)
B unlocks mutex (state: locked -> unlocked), state was locked, so do not notify
C hangs forever. To use notify_one you need to either guarantee at most one waiter (making notify_one pointless) or you need a wait count. If you use only one bit (or when your count saturates, which is the same thing), you either need to notify_all (and deal with the thundering herd) or unconditionally call notify_one (and do away with the fast path). IIRC the original futex paper had a discussion of this.Incidentally, I love the atomic::wait in c++20, although it is not without issues https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p26...).