using System; using System.Diagnostics; using System.Threading; namespace ZeroLevel.Services.Utils { public sealed class Clock : IDisposable { private readonly long _maxIdleTime = TimeSpan.FromSeconds(10).Ticks; private const long TicksMultiplier = 1000 * TimeSpan.TicksPerMillisecond; private readonly ThreadLocal _startTime = new ThreadLocal(() => DateTime.UtcNow, false); private readonly ThreadLocal _startTimestamp = new ThreadLocal(() => Stopwatch.GetTimestamp(), false); public DateTime UtcNow { get { double endTimestamp = Stopwatch.GetTimestamp(); var durationInTicks = (endTimestamp - _startTimestamp.Value) / Stopwatch.Frequency * TicksMultiplier; if (durationInTicks >= _maxIdleTime) { _startTimestamp.Value = Stopwatch.GetTimestamp(); _startTime.Value = DateTime.UtcNow; return _startTime.Value; } return _startTime.Value.AddTicks((long)durationInTicks); } } public void Dispose() { _startTime.Dispose(); _startTimestamp.Dispose(); } } }