/SS14.Server/Timing/TimerQueueTimer_.cs

https://gitlab.com/matt81093/space-station-14 · C# · 144 lines · 102 code · 25 blank · 17 comment · 1 complexity · 2bf7e4fd83c3ec60578061e42547a8ae MD5 · raw file

  1. using System;
  2. using System.Runtime.InteropServices;
  3. namespace ServerServices.Timing
  4. {
  5. public class TimerQueueTimer : IDisposable
  6. {
  7. IntPtr phNewTimer; // Handle to the timer.
  8. #region Win32 TimerQueueTimer Functions
  9. [DllImport("kernel32.dll")]
  10. static extern bool CreateTimerQueueTimer(
  11. out IntPtr phNewTimer, // phNewTimer - Pointer to a handle; this is an out value
  12. IntPtr TimerQueue, // TimerQueue - Timer queue handle. For the default timer queue, NULL
  13. WaitOrTimerDelegate Callback, // Callback - Pointer to the callback function
  14. IntPtr Parameter, // Parameter - Value passed to the callback function
  15. uint DueTime, // DueTime - Time (milliseconds), before the timer is set to the signaled state for the first time
  16. uint Period, // Period - Timer period (milliseconds). If zero, timer is signaled only once
  17. uint Flags // Flags - One or more of the next values (table taken from MSDN):
  18. // WT_EXECUTEINTIMERTHREAD The callback function is invoked by the timer thread itself. This flag should be used only for short tasks or it could affect other timer operations.
  19. // WT_EXECUTEINIOTHREAD The callback function is queued to an I/O worker thread. This flag should be used if the function should be executed in a thread that waits in an alertable state.
  20. // The callback function is queued as an APC. Be sure to address reentrancy issues if the function performs an alertable wait operation.
  21. // WT_EXECUTEINPERSISTENTTHREAD The callback function is queued to a thread that never terminates. This flag should be used only for short tasks or it could affect other timer operations.
  22. // Note that currently no worker thread is persistent, although no worker thread will terminate if there are any pending I/O requests.
  23. // WT_EXECUTELONGFUNCTION Specifies that the callback function can perform a long wait. This flag helps the system to decide if it should create a new thread.
  24. // WT_EXECUTEONLYONCE The timer will be set to the signaled state only once.
  25. );
  26. [DllImport("kernel32.dll")]
  27. static extern bool DeleteTimerQueueTimer(
  28. IntPtr timerQueue, // TimerQueue - A handle to the (default) timer queue
  29. IntPtr timer, // Timer - A handle to the timer
  30. IntPtr completionEvent // CompletionEvent - A handle to an optional event to be signaled when the function is successful and all callback functions have completed. Can be NULL.
  31. );
  32. [DllImport("kernel32.dll")]
  33. private static extern bool ChangeTimerQueueTimer(
  34. IntPtr timerQueue,
  35. IntPtr timer,
  36. uint dueTime,
  37. uint period
  38. );
  39. [DllImport("kernel32.dll")]
  40. static extern bool DeleteTimerQueue(IntPtr TimerQueue);
  41. [DllImport("kernel32.dll", SetLastError = true)]
  42. [return: MarshalAs(UnmanagedType.Bool)]
  43. static extern bool CloseHandle(IntPtr hObject);
  44. #endregion
  45. public delegate void WaitOrTimerDelegate(IntPtr lpParameter, bool timerOrWaitFired);
  46. public TimerQueueTimer()
  47. {
  48. }
  49. public void Create(uint dueTime, uint period, WaitOrTimerDelegate callbackDelegate)
  50. {
  51. IntPtr pParameter = IntPtr.Zero;
  52. bool success = CreateTimerQueueTimer(
  53. // Timer handle
  54. out phNewTimer,
  55. // Default timer queue. IntPtr.Zero is just a constant value that represents a null pointer.
  56. IntPtr.Zero,
  57. // Timer callback function
  58. callbackDelegate,
  59. // Callback function parameter
  60. pParameter,
  61. // Time (milliseconds), before the timer is set to the signaled state for the first time.
  62. dueTime,
  63. // Period - Timer period (milliseconds). If zero, timer is signaled only once.
  64. period,
  65. (uint)Flag.WT_EXECUTELONGFUNCTION | (uint)Flag.WT_EXECUTEINIOTHREAD);
  66. if (!success)
  67. throw new QueueTimerException("Error creating QueueTimer");
  68. }
  69. public void Delete()
  70. {
  71. //bool success = DeleteTimerQueue(IntPtr.Zero);
  72. bool success = DeleteTimerQueueTimer(
  73. IntPtr.Zero, // TimerQueue - A handle to the (default) timer queue
  74. phNewTimer, // Timer - A handle to t7he timer
  75. IntPtr.Zero // CompletionEvent - A handle to an optional event to be signaled when the function is successful and all callback functions have completed. Can be NULL.
  76. );
  77. int error = Marshal.GetLastWin32Error();
  78. //CloseHandle(phNewTimer);
  79. }
  80. public void Change(uint dueTime, uint period)
  81. {
  82. bool success = ChangeTimerQueueTimer(
  83. IntPtr.Zero,
  84. phNewTimer,
  85. dueTime,
  86. period
  87. );
  88. int error = Marshal.GetLastWin32Error();
  89. }
  90. public enum Flag: uint
  91. {
  92. WT_EXECUTEDEFAULT = 0x00000000,
  93. WT_EXECUTEINIOTHREAD = 0x00000001,
  94. //WT_EXECUTEINWAITTHREAD = 0x00000004,
  95. WT_EXECUTEONLYONCE = 0x00000008,
  96. WT_EXECUTELONGFUNCTION = 0x00000010,
  97. WT_EXECUTEINTIMERTHREAD = 0x00000020,
  98. WT_EXECUTEINPERSISTENTTHREAD = 0x00000080,
  99. //WT_TRANSFER_IMPERSONATION = 0x00000100
  100. }
  101. #region IDisposable Members
  102. void IDisposable.Dispose()
  103. {
  104. Delete();
  105. }
  106. #endregion
  107. }
  108. public class QueueTimerException : Exception
  109. {
  110. public QueueTimerException(string message)
  111. : base(message)
  112. {
  113. }
  114. public QueueTimerException(string message, Exception innerException)
  115. : base(message, innerException)
  116. {
  117. }
  118. }
  119. }