KTimeManager.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Threading;
  6. namespace Ryujinx.HLE.HOS.Kernel
  7. {
  8. class KTimeManager : IDisposable
  9. {
  10. private class WaitingObject
  11. {
  12. public IKFutureSchedulerObject Object { get; private set; }
  13. public long TimePoint { get; private set; }
  14. public WaitingObject(IKFutureSchedulerObject Object, long TimePoint)
  15. {
  16. this.Object = Object;
  17. this.TimePoint = TimePoint;
  18. }
  19. }
  20. private List<WaitingObject> WaitingObjects;
  21. private AutoResetEvent WaitEvent;
  22. private Stopwatch Counter;
  23. private bool KeepRunning;
  24. public KTimeManager()
  25. {
  26. WaitingObjects = new List<WaitingObject>();
  27. Counter = new Stopwatch();
  28. Counter.Start();
  29. KeepRunning = true;
  30. Thread Work = new Thread(WaitAndCheckScheduledObjects);
  31. Work.Start();
  32. }
  33. public void ScheduleFutureInvocation(IKFutureSchedulerObject Object, long Timeout)
  34. {
  35. lock (WaitingObjects)
  36. {
  37. long TimePoint = Counter.ElapsedMilliseconds + ConvertNanosecondsToMilliseconds(Timeout);
  38. WaitingObjects.Add(new WaitingObject(Object, TimePoint));
  39. }
  40. WaitEvent.Set();
  41. }
  42. private long ConvertNanosecondsToMilliseconds(long Timeout)
  43. {
  44. Timeout /= 1000000;
  45. if ((ulong)Timeout > int.MaxValue)
  46. {
  47. return int.MaxValue;
  48. }
  49. return Timeout;
  50. }
  51. public void UnscheduleFutureInvocation(IKFutureSchedulerObject Object)
  52. {
  53. lock (WaitingObjects)
  54. {
  55. WaitingObjects.RemoveAll(x => x.Object == Object);
  56. }
  57. }
  58. private void WaitAndCheckScheduledObjects()
  59. {
  60. using (WaitEvent = new AutoResetEvent(false))
  61. {
  62. while (KeepRunning)
  63. {
  64. Monitor.Enter(WaitingObjects);
  65. WaitingObject Next = WaitingObjects.OrderBy(x => x.TimePoint).FirstOrDefault();
  66. Monitor.Exit(WaitingObjects);
  67. if (Next != null)
  68. {
  69. long TimePoint = Counter.ElapsedMilliseconds;
  70. if (Next.TimePoint > TimePoint)
  71. {
  72. WaitEvent.WaitOne((int)(Next.TimePoint - TimePoint));
  73. }
  74. Monitor.Enter(WaitingObjects);
  75. bool TimeUp = Counter.ElapsedMilliseconds >= Next.TimePoint && WaitingObjects.Remove(Next);
  76. Monitor.Exit(WaitingObjects);
  77. if (TimeUp)
  78. {
  79. Next.Object.TimeUp();
  80. }
  81. }
  82. else
  83. {
  84. WaitEvent.WaitOne();
  85. }
  86. }
  87. }
  88. }
  89. public void Dispose()
  90. {
  91. Dispose(true);
  92. }
  93. protected virtual void Dispose(bool Disposing)
  94. {
  95. if (Disposing)
  96. {
  97. KeepRunning = false;
  98. WaitEvent?.Set();
  99. }
  100. }
  101. }
  102. }