_gchandle weak v2

This commit is contained in:
2023-08-27 13:18:32 +03:00
parent 70edfbb146
commit 3df1e86ecb

View File

@@ -419,7 +419,7 @@ namespace FlaxEngine.Interop
// Rolling numbers for handles, two bits reserved for the type // Rolling numbers for handles, two bits reserved for the type
//private static ulong normalHandleAccumulator = ((ulong)GCHandleType.Normal << 62) & 0xC000000000000000; //private static ulong normalHandleAccumulator = ((ulong)GCHandleType.Normal << 62) & 0xC000000000000000;
//private static ulong pinnedHandleAccumulator = ((ulong)GCHandleType.Pinned << 62) & 0xC000000000000000; //private static ulong pinnedHandleAccumulator = ((ulong)GCHandleType.Pinned << 62) & 0xC000000000000000;
//private static ulong weakHandleAccumulator = ((ulong)GCHandleType.Weak << 62) & 0xC000000000000000; private static ulong weakHandleAccumulator = ((ulong)GCHandleType.Normal << 62) & 0xC000000000000000;
// Dictionaries for storing the valid handles. // Dictionaries for storing the valid handles.
// Note: Using locks seems to be generally the fastest when adding or fetching from the dictionary. // Note: Using locks seems to be generally the fastest when adding or fetching from the dictionary.
@@ -432,8 +432,8 @@ namespace FlaxEngine.Interop
// Manage double-buffered pool for weak handles in order to avoid collecting in-flight handles. // Manage double-buffered pool for weak handles in order to avoid collecting in-flight handles.
// Periodically when the pools are being accessed and conditions are met, the other pool is cleared and swapped. // Periodically when the pools are being accessed and conditions are met, the other pool is cleared and swapped.
private static HashSet<IntPtr> weakPool = new(); private static Dictionary<IntPtr, object> weakPool = new();
private static HashSet<IntPtr> weakPoolOther = new(); private static Dictionary<IntPtr, object> weakPoolOther = new();
private static object weakPoolLock = new object(); private static object weakPoolLock = new object();
private static ulong nextWeakPoolCollection; private static ulong nextWeakPoolCollection;
private static ulong weakPoolCycle; private static ulong weakPoolCycle;
@@ -451,12 +451,12 @@ namespace FlaxEngine.Interop
nextWeakPoolCollection = 0; nextWeakPoolCollection = 0;
//ulong currentCycle = weakPoolCycle; ulong currentCycle = weakPoolCycle;
//lock (weakPoolLock) lock (weakPoolLock)
{ {
//if (currentCycle != weakPoolCycle) if (currentCycle != weakPoolCycle)
// return; return;
weakPoolCycle++; weakPoolCycle++;
@@ -471,13 +471,6 @@ namespace FlaxEngine.Interop
return; return;
lastWeakPoolCollectionTime = System.Diagnostics.Stopwatch.GetTimestamp(); lastWeakPoolCollectionTime = System.Diagnostics.Stopwatch.GetTimestamp();
foreach (IntPtr ptr in weakPoolOther)
{
GCHandle gcHandle = GCHandle.FromIntPtr(ptr);
gcHandle.Free();
}
// Swap the pools and release the oldest pool for GC // Swap the pools and release the oldest pool for GC
(weakPool, weakPoolOther) = (weakPoolOther, weakPool); (weakPool, weakPoolOther) = (weakPoolOther, weakPool);
weakPool.Clear(); weakPool.Clear();
@@ -498,24 +491,26 @@ namespace FlaxEngine.Interop
//[MethodImpl(MethodImplOptions.AggressiveInlining)] //[MethodImpl(MethodImplOptions.AggressiveInlining)]
//private static GCHandleType GetHandleType(IntPtr handle) => (GCHandleType)(((ulong)handle & 0xC000000000000000) >> 62); //private static GCHandleType GetHandleType(IntPtr handle) => (GCHandleType)(((ulong)handle & 0xC000000000000000) >> 62);
private static bool IsWeakHandle(IntPtr handle) => ((ulong)handle & 0xC000000000000000) >> 62 == 2;
internal static IntPtr AllocateHandle(object value, GCHandleType type) internal static IntPtr AllocateHandle(object value, GCHandleType type)
{ {
GCHandleType type2 = type;
if (type == GCHandleType.Weak || type == GCHandleType.WeakTrackResurrection) if (type == GCHandleType.Weak || type == GCHandleType.WeakTrackResurrection)
{ {
type2 = GCHandleType.Normal;
lock (weakPoolLock)
{
IntPtr handle = (IntPtr)(++weakHandleAccumulator);
weakPool.Add(handle, value);
return handle;
}
} }
else
GCHandle gcHandle = GCHandle.Alloc(value, type2);
IntPtr handle = GCHandle.ToIntPtr(gcHandle);
if (type == GCHandleType.Weak || type == GCHandleType.WeakTrackResurrection)
{ {
//TryCollectWeakHandles(); GCHandle gcHandle = GCHandle.Alloc(value, type);
weakPool.Add(handle/*, gcHandle.Target*/); IntPtr handle = GCHandle.ToIntPtr(gcHandle);
return handle;
} }
return handle;
/*IntPtr handle = NewHandle(type); /*IntPtr handle = NewHandle(type);
switch (type) switch (type)
{ {
@@ -541,8 +536,14 @@ namespace FlaxEngine.Interop
internal static object GetObject(IntPtr handle) internal static object GetObject(IntPtr handle)
{ {
//if (weakPool.Contains(handle) || weakPoolOther.Contains(handle)) if (IsWeakHandle(handle))
// handle = handle; lock (weakPoolLock)
{
if (weakPool.TryGetValue(handle, out object weakValue) || weakPoolOther.TryGetValue(handle, out weakValue))
{
return weakValue;
}
}
GCHandle gcHandle = GCHandle.FromIntPtr(handle); GCHandle gcHandle = GCHandle.FromIntPtr(handle);
@@ -584,6 +585,21 @@ namespace FlaxEngine.Interop
internal static void SetObject(IntPtr handle, object value) internal static void SetObject(IntPtr handle, object value)
{ {
if (IsWeakHandle(handle))
lock (weakPoolLock)
{
if (weakPool.ContainsKey(handle))
{
weakPool[handle] = value;
return;
}
else if (weakPoolOther.ContainsKey(handle))
{
weakPoolOther[handle] = value;
return;
}
}
GCHandle gcHandle = GCHandle.FromIntPtr(handle); GCHandle gcHandle = GCHandle.FromIntPtr(handle);
if (!gcHandle.IsAllocated) if (!gcHandle.IsAllocated)
@@ -644,8 +660,12 @@ namespace FlaxEngine.Interop
internal static void FreeHandle(IntPtr handle) internal static void FreeHandle(IntPtr handle)
{ {
if (weakPool.Contains(handle) || weakPoolOther.Contains(handle)) if (IsWeakHandle(handle))
return; lock (weakPoolLock)
{
if (weakPool.ContainsKey(handle) || weakPoolOther.ContainsKey(handle))
return;
}
GCHandle gcHandle = GCHandle.FromIntPtr(handle); GCHandle gcHandle = GCHandle.FromIntPtr(handle);