private bool WaitForSignal(int timeoutMs) { Debug.Assert(timeoutMs > 0 || timeoutMs == -1); _onWait(); while (true) { if (!WaitCore(timeoutMs)) { // Unregister the waiter. The wait subsystem used above guarantees that a thread that wakes due to a timeout does // not observe a signal to the object being waited upon. _separated._counts.InterlockedDecrementWaiterCount(); return(false); } // Unregister the waiter if this thread will not be waiting anymore, and try to acquire the semaphore Counts counts = _separated._counts; while (true) { Debug.Assert(counts.WaiterCount != 0); Counts newCounts = counts; if (counts.SignalCount != 0) { newCounts.DecrementSignalCount(); newCounts.DecrementWaiterCount(); } // This waiter has woken up and this needs to be reflected in the count of waiters signaled to wake if (counts.CountOfWaitersSignaledToWake != 0) { newCounts.DecrementCountOfWaitersSignaledToWake(); } Counts countsBeforeUpdate = _separated._counts.InterlockedCompareExchange(newCounts, counts); if (countsBeforeUpdate == counts) { if (counts.SignalCount != 0) { return(true); } break; } counts = countsBeforeUpdate; } } }