public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
{
CheckState();
if (millisecondsTimeout < -1)
{
throw new ArgumentOutOfRangeException("millisecondsTimeout",
"millisecondsTimeout is a negative number other than -1");
}
Watch sw = Watch.StartNew();
Func <bool> stopCondition = () => millisecondsTimeout >= 0 && sw.ElapsedMilliseconds > millisecondsTimeout;
do
{
bool shouldWait;
int result;
do
{
cancellationToken.ThrowIfCancellationRequested();
if (stopCondition())
{
return(false);
}
shouldWait = true;
result = currCount;
if (result > 0)
{
shouldWait = false;
}
else
{
break;
}
} while (Interlocked.CompareExchange(ref currCount, result - 1, result) != result);
if (!shouldWait)
{
if (result == 1)
{
handle.Reset();
}
break;
}
SpinWait wait = new SpinWait();
while (Thread.VolatileRead(ref currCount) <= 0)
{
cancellationToken.ThrowIfCancellationRequested();
if (stopCondition())
{
return(false);
}
if (wait.Count > spinCount)
{
int timeout = millisecondsTimeout < 0 ? deepSleepTime :
Math.Min(Math.Max(millisecondsTimeout - (int)sw.ElapsedMilliseconds, 1), deepSleepTime);
handle.WaitOne(timeout);
}
else
{
wait.SpinOnce();
}
}
} while (true);
return(true);
}