73 lines
1.9 KiB
C#
73 lines
1.9 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
|
|
namespace PerfectNumbers.Core;
|
|
|
|
internal readonly struct PrimeTestTimeLimit
|
|
{
|
|
private readonly long _deadlineTimestamp;
|
|
|
|
private PrimeTestTimeLimit(bool isActive, long deadlineTimestamp)
|
|
{
|
|
IsActive = isActive;
|
|
_deadlineTimestamp = deadlineTimestamp;
|
|
}
|
|
|
|
internal bool IsActive { get; }
|
|
|
|
internal static bool TryCreate(TimeSpan? timeLimit, out PrimeTestTimeLimit limit)
|
|
{
|
|
if (!timeLimit.HasValue)
|
|
{
|
|
limit = new PrimeTestTimeLimit(isActive: false, deadlineTimestamp: long.MaxValue);
|
|
return true;
|
|
}
|
|
|
|
TimeSpan limitValue = timeLimit.GetValueOrDefault();
|
|
if (limitValue <= TimeSpan.Zero)
|
|
{
|
|
limit = new PrimeTestTimeLimit(isActive: true, deadlineTimestamp: long.MinValue);
|
|
return false;
|
|
}
|
|
|
|
double seconds = limitValue.TotalSeconds;
|
|
if (double.IsInfinity(seconds))
|
|
{
|
|
limit = new PrimeTestTimeLimit(isActive: true, deadlineTimestamp: long.MaxValue);
|
|
return true;
|
|
}
|
|
|
|
double scaled = seconds * Stopwatch.Frequency;
|
|
long limitTicks = scaled >= long.MaxValue ? long.MaxValue : (long)scaled;
|
|
long startTimestamp = Stopwatch.GetTimestamp();
|
|
long deadline = startTimestamp <= long.MaxValue - limitTicks ? startTimestamp + limitTicks : long.MaxValue;
|
|
if (deadline < startTimestamp)
|
|
{
|
|
deadline = long.MaxValue;
|
|
}
|
|
|
|
limit = new PrimeTestTimeLimit(isActive: true, deadlineTimestamp: deadline);
|
|
return true;
|
|
}
|
|
|
|
internal bool HasExpired()
|
|
{
|
|
if (!IsActive)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (_deadlineTimestamp == long.MaxValue)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (_deadlineTimestamp == long.MinValue)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return Stopwatch.GetTimestamp() >= _deadlineTimestamp;
|
|
}
|
|
}
|