HandleCollector.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // reference from https://referencesource.microsoft.com/#WindowsBase/Shared/MS/Win32/HandleCollector.cs,d0f99220d8e1b708
  2. using System;
  3. using System.Runtime.InteropServices;
  4. namespace HandyControl.Tools.Interop;
  5. internal static class HandleCollector
  6. {
  7. private static HandleType[] HandleTypes;
  8. private static int HandleTypeCount;
  9. private static readonly object HandleMutex = new();
  10. internal static IntPtr Add(IntPtr handle, int type)
  11. {
  12. HandleTypes[type - 1].Add();
  13. return handle;
  14. }
  15. [System.Security.SecuritySafeCritical]
  16. internal static SafeHandle Add(SafeHandle handle, int type)
  17. {
  18. HandleTypes[type - 1].Add();
  19. return handle;
  20. }
  21. internal static void Add(int type)
  22. {
  23. HandleTypes[type - 1].Add();
  24. }
  25. internal static int RegisterType(string typeName, int expense, int initialThreshold)
  26. {
  27. lock (HandleMutex)
  28. {
  29. if (HandleTypeCount == 0 || HandleTypeCount == HandleTypes.Length)
  30. {
  31. HandleType[] newTypes = new HandleType[HandleTypeCount + 10];
  32. if (HandleTypes != null)
  33. {
  34. Array.Copy(HandleTypes, 0, newTypes, 0, HandleTypeCount);
  35. }
  36. HandleTypes = newTypes;
  37. }
  38. HandleTypes[HandleTypeCount++] = new HandleType(expense, initialThreshold);
  39. return HandleTypeCount;
  40. }
  41. }
  42. internal static IntPtr Remove(IntPtr handle, int type)
  43. {
  44. HandleTypes[type - 1].Remove();
  45. return handle;
  46. }
  47. [System.Security.SecuritySafeCritical]
  48. internal static SafeHandle Remove(SafeHandle handle, int type)
  49. {
  50. HandleTypes[type - 1].Remove();
  51. return handle;
  52. }
  53. internal static void Remove(int type)
  54. {
  55. HandleTypes[type - 1].Remove();
  56. }
  57. private class HandleType
  58. {
  59. private readonly int _initialThreshHold;
  60. private int _threshHold;
  61. private int _handleCount;
  62. private readonly int _deltaPercent;
  63. internal HandleType(int expense, int initialThreshHold)
  64. {
  65. _initialThreshHold = initialThreshHold;
  66. _threshHold = initialThreshHold;
  67. _deltaPercent = 100 - expense;
  68. }
  69. internal void Add()
  70. {
  71. lock (this)
  72. {
  73. _handleCount++;
  74. var performCollect = NeedCollection();
  75. if (!performCollect)
  76. {
  77. return;
  78. }
  79. }
  80. GC.Collect();
  81. var sleep = (100 - _deltaPercent) / 4;
  82. System.Threading.Thread.Sleep(sleep);
  83. }
  84. private bool NeedCollection()
  85. {
  86. if (_handleCount > _threshHold)
  87. {
  88. _threshHold = _handleCount + _handleCount * _deltaPercent / 100;
  89. return true;
  90. }
  91. var oldThreshHold = 100 * _threshHold / (100 + _deltaPercent);
  92. if (oldThreshHold >= _initialThreshHold && _handleCount < (int) (oldThreshHold * .9F))
  93. {
  94. _threshHold = oldThreshHold;
  95. }
  96. return false;
  97. }
  98. internal void Remove()
  99. {
  100. lock (this)
  101. {
  102. _handleCount--;
  103. _handleCount = Math.Max(0, _handleCount);
  104. }
  105. }
  106. }
  107. }