132 lines
3.7 KiB
C#
132 lines
3.7 KiB
C#
// reference from https://referencesource.microsoft.com/#WindowsBase/Shared/MS/Win32/HandleCollector.cs,d0f99220d8e1b708
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace HandyControl.Tools.Interop
|
|
{
|
|
internal static class HandleCollector
|
|
{
|
|
private static HandleType[] HandleTypes;
|
|
private static int HandleTypeCount;
|
|
|
|
private static readonly object HandleMutex = new object();
|
|
|
|
internal static IntPtr Add(IntPtr handle, int type)
|
|
{
|
|
HandleTypes[type - 1].Add();
|
|
return handle;
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical]
|
|
internal static SafeHandle Add(SafeHandle handle, int type)
|
|
{
|
|
HandleTypes[type - 1].Add();
|
|
return handle;
|
|
}
|
|
|
|
internal static void Add(int type)
|
|
{
|
|
HandleTypes[type - 1].Add();
|
|
}
|
|
|
|
internal static int RegisterType(string typeName, int expense, int initialThreshold)
|
|
{
|
|
lock (HandleMutex)
|
|
{
|
|
if (HandleTypeCount == 0 || HandleTypeCount == HandleTypes.Length)
|
|
{
|
|
HandleType[] newTypes = new HandleType[HandleTypeCount + 10];
|
|
if (HandleTypes != null)
|
|
{
|
|
Array.Copy(HandleTypes, 0, newTypes, 0, HandleTypeCount);
|
|
}
|
|
HandleTypes = newTypes;
|
|
}
|
|
|
|
HandleTypes[HandleTypeCount++] = new HandleType(expense, initialThreshold);
|
|
return HandleTypeCount;
|
|
}
|
|
}
|
|
|
|
internal static IntPtr Remove(IntPtr handle, int type)
|
|
{
|
|
HandleTypes[type - 1].Remove();
|
|
return handle;
|
|
}
|
|
|
|
[System.Security.SecuritySafeCritical]
|
|
internal static SafeHandle Remove(SafeHandle handle, int type)
|
|
{
|
|
HandleTypes[type - 1].Remove();
|
|
return handle;
|
|
}
|
|
|
|
internal static void Remove(int type)
|
|
{
|
|
HandleTypes[type - 1].Remove();
|
|
}
|
|
|
|
private class HandleType
|
|
{
|
|
private readonly int _initialThreshHold;
|
|
private int _threshHold;
|
|
private int _handleCount;
|
|
private readonly int _deltaPercent;
|
|
|
|
internal HandleType(int expense, int initialThreshHold)
|
|
{
|
|
_initialThreshHold = initialThreshHold;
|
|
_threshHold = initialThreshHold;
|
|
_deltaPercent = 100 - expense;
|
|
}
|
|
|
|
internal void Add()
|
|
{
|
|
lock (this)
|
|
{
|
|
_handleCount++;
|
|
var performCollect = NeedCollection();
|
|
|
|
if (!performCollect)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
GC.Collect();
|
|
|
|
var sleep = (100 - _deltaPercent) / 4;
|
|
System.Threading.Thread.Sleep(sleep);
|
|
}
|
|
|
|
private bool NeedCollection()
|
|
{
|
|
|
|
if (_handleCount > _threshHold)
|
|
{
|
|
_threshHold = _handleCount + _handleCount * _deltaPercent / 100;
|
|
return true;
|
|
}
|
|
|
|
var oldThreshHold = 100 * _threshHold / (100 + _deltaPercent);
|
|
if (oldThreshHold >= _initialThreshHold && _handleCount < (int) (oldThreshHold * .9F))
|
|
{
|
|
_threshHold = oldThreshHold;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal void Remove()
|
|
{
|
|
lock (this)
|
|
{
|
|
_handleCount--;
|
|
|
|
_handleCount = Math.Max(0, _handleCount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|