e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
189 lines
5.5 KiB
C#
189 lines
5.5 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace System.Runtime
|
|
{
|
|
using System;
|
|
using System.Threading;
|
|
|
|
struct TimeoutHelper
|
|
{
|
|
DateTime deadline;
|
|
bool deadlineSet;
|
|
TimeSpan originalTimeout;
|
|
public static readonly TimeSpan MaxWait = TimeSpan.FromMilliseconds(Int32.MaxValue);
|
|
|
|
public TimeoutHelper(TimeSpan timeout)
|
|
{
|
|
Fx.Assert(timeout >= TimeSpan.Zero, "timeout must be non-negative");
|
|
|
|
this.originalTimeout = timeout;
|
|
this.deadline = DateTime.MaxValue;
|
|
this.deadlineSet = (timeout == TimeSpan.MaxValue);
|
|
}
|
|
|
|
public TimeSpan OriginalTimeout
|
|
{
|
|
get { return this.originalTimeout; }
|
|
}
|
|
|
|
public static bool IsTooLarge(TimeSpan timeout)
|
|
{
|
|
return (timeout > TimeoutHelper.MaxWait) && (timeout != TimeSpan.MaxValue);
|
|
}
|
|
|
|
public static TimeSpan FromMilliseconds(int milliseconds)
|
|
{
|
|
if (milliseconds == Timeout.Infinite)
|
|
{
|
|
return TimeSpan.MaxValue;
|
|
}
|
|
else
|
|
{
|
|
return TimeSpan.FromMilliseconds(milliseconds);
|
|
}
|
|
}
|
|
|
|
public static int ToMilliseconds(TimeSpan timeout)
|
|
{
|
|
if (timeout == TimeSpan.MaxValue)
|
|
{
|
|
return Timeout.Infinite;
|
|
}
|
|
else
|
|
{
|
|
long ticks = Ticks.FromTimeSpan(timeout);
|
|
if (ticks / TimeSpan.TicksPerMillisecond > int.MaxValue)
|
|
{
|
|
return int.MaxValue;
|
|
}
|
|
return Ticks.ToMilliseconds(ticks);
|
|
}
|
|
}
|
|
|
|
public static TimeSpan Min(TimeSpan val1, TimeSpan val2)
|
|
{
|
|
if (val1 > val2)
|
|
{
|
|
return val2;
|
|
}
|
|
else
|
|
{
|
|
return val1;
|
|
}
|
|
}
|
|
|
|
public static TimeSpan Add(TimeSpan timeout1, TimeSpan timeout2)
|
|
{
|
|
return Ticks.ToTimeSpan(Ticks.Add(Ticks.FromTimeSpan(timeout1), Ticks.FromTimeSpan(timeout2)));
|
|
}
|
|
|
|
public static DateTime Add(DateTime time, TimeSpan timeout)
|
|
{
|
|
if (timeout >= TimeSpan.Zero && DateTime.MaxValue - time <= timeout)
|
|
{
|
|
return DateTime.MaxValue;
|
|
}
|
|
if (timeout <= TimeSpan.Zero && DateTime.MinValue - time >= timeout)
|
|
{
|
|
return DateTime.MinValue;
|
|
}
|
|
return time + timeout;
|
|
}
|
|
|
|
public static DateTime Subtract(DateTime time, TimeSpan timeout)
|
|
{
|
|
return Add(time, TimeSpan.Zero - timeout);
|
|
}
|
|
|
|
public static TimeSpan Divide(TimeSpan timeout, int factor)
|
|
{
|
|
if (timeout == TimeSpan.MaxValue)
|
|
{
|
|
return TimeSpan.MaxValue;
|
|
}
|
|
|
|
return Ticks.ToTimeSpan((Ticks.FromTimeSpan(timeout) / factor) + 1);
|
|
}
|
|
|
|
public TimeSpan RemainingTime()
|
|
{
|
|
if (!this.deadlineSet)
|
|
{
|
|
this.SetDeadline();
|
|
return this.originalTimeout;
|
|
}
|
|
else if (this.deadline == DateTime.MaxValue)
|
|
{
|
|
return TimeSpan.MaxValue;
|
|
}
|
|
else
|
|
{
|
|
TimeSpan remaining = this.deadline - DateTime.UtcNow;
|
|
if (remaining <= TimeSpan.Zero)
|
|
{
|
|
return TimeSpan.Zero;
|
|
}
|
|
else
|
|
{
|
|
return remaining;
|
|
}
|
|
}
|
|
}
|
|
|
|
public TimeSpan ElapsedTime()
|
|
{
|
|
return this.originalTimeout - this.RemainingTime();
|
|
}
|
|
|
|
void SetDeadline()
|
|
{
|
|
Fx.Assert(!deadlineSet, "TimeoutHelper deadline set twice.");
|
|
this.deadline = DateTime.UtcNow + this.originalTimeout;
|
|
this.deadlineSet = true;
|
|
}
|
|
|
|
public static void ThrowIfNegativeArgument(TimeSpan timeout)
|
|
{
|
|
ThrowIfNegativeArgument(timeout, "timeout");
|
|
}
|
|
|
|
public static void ThrowIfNegativeArgument(TimeSpan timeout, string argumentName)
|
|
{
|
|
if (timeout < TimeSpan.Zero)
|
|
{
|
|
throw Fx.Exception.ArgumentOutOfRange(argumentName, timeout, InternalSR.TimeoutMustBeNonNegative(argumentName, timeout));
|
|
}
|
|
}
|
|
|
|
public static void ThrowIfNonPositiveArgument(TimeSpan timeout)
|
|
{
|
|
ThrowIfNonPositiveArgument(timeout, "timeout");
|
|
}
|
|
|
|
public static void ThrowIfNonPositiveArgument(TimeSpan timeout, string argumentName)
|
|
{
|
|
if (timeout <= TimeSpan.Zero)
|
|
{
|
|
throw Fx.Exception.ArgumentOutOfRange(argumentName, timeout, InternalSR.TimeoutMustBePositive(argumentName, timeout));
|
|
}
|
|
}
|
|
|
|
[Fx.Tag.Blocking]
|
|
public static bool WaitOne(WaitHandle waitHandle, TimeSpan timeout)
|
|
{
|
|
ThrowIfNegativeArgument(timeout);
|
|
if (timeout == TimeSpan.MaxValue)
|
|
{
|
|
waitHandle.WaitOne();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return waitHandle.WaitOne(timeout, false);
|
|
}
|
|
}
|
|
}
|
|
}
|