using System; using System.Diagnostics; using System.Threading; using JD.Kernel.Classes; using JD.Kernel.StaticHelpers; namespace JD.Statistics { public sealed class TimerMetric : IDisposable, IComparable, IComparable { #region Variables private long m_ticks; private readonly Stopwatch _stopwatch; private int m_timerRunningCount; private bool m_hasStarted = true; #endregion #region Constructor/Destructor public TimerMetric() : this(true, null) { } public TimerMetric(bool autoStart) : this(autoStart, null) { } public TimerMetric(bool autoStart, Stopwatch timer) { _stopwatch = timer ?? new Stopwatch(); if (autoStart) { SafeStart(_stopwatch); } } public void Dispose() { Stop(_stopwatch); } #endregion #region Properties public TimeSpan Time { get { return new TimeSpan(m_ticks); } } #endregion #region Methods public IDisposable SafeStart() { var timer = new Stopwatch(); return SafeStart(timer); } internal IDisposable SafeStart(Stopwatch timer) { Interlocked.Increment(ref m_timerRunningCount); timer.Start(); m_hasStarted = true; return new DisposableHelper(() => Stop(timer)); } private void Stop(Stopwatch timer) { if (timer.IsRunning) { timer.Stop(); Interlocked.Decrement(ref m_timerRunningCount); Add(timer.Elapsed); } } public int CompareTo(object obj) { TimerMetric metric = obj as TimerMetric; if (metric != null) { return CompareTo(metric); } return 0; } public int CompareTo(TimerMetric metric) { return Time.CompareTo(metric.Time); } /// /// Adds time to the metric. /// public void Add(TimeSpan time) { m_hasStarted = true; InterlockedEx.Add(ref m_ticks, time.Ticks); } public override string ToString() { if (!m_hasStarted) { return "-"; } return $"{(int) Time.TotalMilliseconds} ms"; } #endregion } }