Advertisement
_DarkLex_

HighPrecisionTimer.cs

Jul 24th, 2018
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.59 KB | None | 0 0
  1. #region LICENSE
  2.  
  3. // The contents of this file are subject to the Common Public Attribution
  4. // License Version 1.0. (the "License"); you may not use this file except in
  5. // compliance with the License. You may obtain a copy of the License at
  6. // https://github.com/NiclasOlofsson/MiNET/blob/master/LICENSE.
  7. // The License is based on the Mozilla Public License Version 1.1, but Sections 14
  8. // and 15 have been added to cover use of software over a computer network and
  9. // provide for limited attribution for the Original Developer. In addition, Exhibit A has
  10. // been modified to be consistent with Exhibit B.
  11. //
  12. // Software distributed under the License is distributed on an "AS IS" basis,
  13. // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  14. // the specific language governing rights and limitations under the License.
  15. //
  16. // The Original Code is Niclas Olofsson.
  17. //
  18. // The Original Developer is the Initial Developer. The Initial Developer of
  19. // the Original Code is Niclas Olofsson.
  20. //
  21. // All portions of the code written by Niclas Olofsson are Copyright (c) 2014-2017 Niclas Olofsson.
  22. // All Rights Reserved.
  23.  
  24. #endregion
  25.  
  26. using System;
  27. using System.Diagnostics;
  28. using System.Threading;
  29. using System.Threading.Tasks;
  30. using log4net;
  31.  
  32. namespace MiNET.Utils
  33. {
  34. public class HighPrecisionTimer : IDisposable
  35. {
  36. private static readonly ILog Log = LogManager.GetLogger(typeof (HighPrecisionTimer));
  37.  
  38. public Action<object> Action { get; set; }
  39.  
  40. protected CancellationTokenSource CancelSource;
  41.  
  42. public long Spins = 0;
  43. public long Sleeps = 0;
  44. public long Misses = 0;
  45. public long Yields = 0;
  46.  
  47. public AutoResetEvent AutoReset = new AutoResetEvent(true);
  48.  
  49. public HighPrecisionTimer(int interval, Action<object> action, bool useSignaling = false)
  50. {
  51. Action = action;
  52.  
  53. if (interval < 1)
  54. throw new ArgumentOutOfRangeException();
  55.  
  56. CancelSource = new CancellationTokenSource();
  57.  
  58. var watch = Stopwatch.StartNew();
  59. long nextStop = interval;
  60.  
  61. var task = new Task(() =>
  62. {
  63. Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
  64.  
  65. while (!CancelSource.IsCancellationRequested)
  66. {
  67. long msLeft = nextStop - watch.ElapsedMilliseconds;
  68. if (msLeft <= 0)
  69. {
  70. if (msLeft < -1) Misses++;
  71.  
  72. Action(this);
  73. AutoReset.Reset();
  74.  
  75. // Calculate when the next stop is. If we're too slow on the trigger then we'll skip ticks
  76. nextStop = (long) (interval*(watch.ElapsedMilliseconds/(float) interval + 1f));
  77.  
  78. continue;
  79. }
  80. if (msLeft < 5)
  81. {
  82. Spins++;
  83. var stop = nextStop;
  84.  
  85. if (useSignaling)
  86. {
  87. AutoReset.WaitOne(50);
  88. }
  89.  
  90.  
  91. if (watch.ElapsedMilliseconds < stop)
  92. {
  93. SpinWait.SpinUntil(() => watch.ElapsedMilliseconds >= stop);
  94. }
  95. //long t = nextStop - watch.ElapsedMilliseconds;
  96. //if(t < -5) Log.Warn($"We overslept {t}ms in spin wait");
  97. continue;
  98. }
  99.  
  100. if (msLeft < 16)
  101. {
  102. if (Thread.Yield()) Yields++;
  103.  
  104. Sleeps++;
  105. Thread.Sleep(1);
  106. continue;
  107. }
  108.  
  109. Sleeps++;
  110. Thread.Sleep(Math.Max(1, (int) (msLeft - 16)));
  111. {
  112. //long t = nextStop - watch.ElapsedMilliseconds;
  113. //if (t < -5) Log.Warn($"We overslept {t}ms in thread sleep");
  114. }
  115. }
  116.  
  117. CancelSource.Dispose();
  118. CancelSource = null;
  119.  
  120. AutoReset.Dispose();
  121. AutoReset = null;
  122. }, CancelSource.Token, TaskCreationOptions.LongRunning);
  123.  
  124. task.Start();
  125. }
  126.  
  127. public void Dispose()
  128. {
  129. CancelSource.Cancel();
  130. AutoReset?.Set();
  131. }
  132. }
  133. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement