Aha! I see the problem. Indeed if statepart == -1, then a waiter can
constantly spin in wait() - consume a semaphore count, see no
generation change, release a semaphore count, and so on.
It seems that this variant of eventcount is not "all that good" in
For your particular problem you may try the following algorithm:
eventcount(HANDLE g_sema, unsigned volatile* waiter_count)
waiter_count_ = waiter_count;
sema_ = g_sema;
long wc = *waiter_count_;
if (wc <= 0)
unsigned wc0 = _InterlockedCompareExchange(waiter_count_, wc - 1,
if (wc0 == wc)
ReleaseSemaphore(sema_, 1, 0);
wc = wc0;
long volatile* waiter_count_;
I've simplified it by completely removing "wait generations". Since in
your problem all waiters are identical (it's OK to wakeup any waiter),
it should not be a problem.
CAUTION: the algorithm is untested and typed in notepad.