_managed handle pool start
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
#define USE_CONCURRENT_DICT
|
||||
#define USE_GCHANDLE
|
||||
//#define TRACK_HANDLES
|
||||
#define TRACK_HANDLES
|
||||
|
||||
#if USE_NETCORE
|
||||
using System;
|
||||
@@ -368,10 +368,17 @@ namespace FlaxEngine.Interop
|
||||
private static HashSet<IntPtr> _weakHandles = new HashSet<nint>();
|
||||
private static ConcurrentDictionary<IntPtr, string> _handles = new();
|
||||
private static ConcurrentDictionary<IntPtr, string> _handles2 = new();
|
||||
private static long _allocations = 0;
|
||||
private static long _deallocations = 0;
|
||||
|
||||
public static long Allocations => Interlocked.Read(ref _allocations);
|
||||
public static long Deallocations => Interlocked.Read(ref _deallocations);
|
||||
#endif
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ManagedHandle(IntPtr handle) => this.handle = GCHandle.FromIntPtr(handle);
|
||||
|
||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ManagedHandle(object value, GCHandleType type) //=> handle = GCHandle.Alloc(value, type);
|
||||
{
|
||||
#if TRACK_HANDLES
|
||||
@@ -394,6 +401,7 @@ namespace FlaxEngine.Interop
|
||||
type = type;
|
||||
_handles2.TryAdd((IntPtr)handle, value?.GetType().FullName ?? "");
|
||||
}
|
||||
Interlocked.Increment(ref _allocations);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
@@ -430,14 +438,25 @@ namespace FlaxEngine.Interop
|
||||
{
|
||||
handle = handle;
|
||||
}
|
||||
Interlocked.Increment(ref _deallocations);
|
||||
#endif
|
||||
handle.Free();
|
||||
}
|
||||
|
||||
|
||||
public object Target => handle.Target;
|
||||
public object Target
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => handle.Target;
|
||||
|
||||
public bool IsAllocated => handle.IsAllocated;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => handle.Target = value;
|
||||
}
|
||||
|
||||
public bool IsAllocated
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => handle.IsAllocated;
|
||||
}
|
||||
#else
|
||||
public void Free()
|
||||
{
|
||||
@@ -485,22 +504,64 @@ namespace FlaxEngine.Interop
|
||||
public static IntPtr ToIntPtr(ManagedHandle value) => value.handle;
|
||||
#endif
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override int GetHashCode() => handle.GetHashCode();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override bool Equals(object obj) => obj is ManagedHandle other && handle == other.handle;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(ManagedHandle other) => handle == other.handle;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(ManagedHandle a, ManagedHandle b) => a.handle == b.handle;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(ManagedHandle a, ManagedHandle b) => a.handle != b.handle;
|
||||
|
||||
#if USE_GCHANDLE
|
||||
/// <summary>
|
||||
/// A pool of shared managed handles used with short-lived temporary GCHandle allocations during interop.
|
||||
/// </summary>
|
||||
internal static class ManagedHandlePool
|
||||
{
|
||||
[ThreadStatic]
|
||||
private static List<(bool InUse, ManagedHandle Handle)> _pool;
|
||||
|
||||
internal static void TryCollectWeakHandles(bool force = false)
|
||||
{
|
||||
}
|
||||
|
||||
internal static ManagedHandle Rent()
|
||||
{
|
||||
foreach (ref var tuple in CollectionsMarshal.AsSpan(_pool))
|
||||
{
|
||||
if (tuple.InUse)
|
||||
continue;
|
||||
|
||||
tuple.InUse = true;
|
||||
return tuple.Handle;
|
||||
}
|
||||
|
||||
var newTuple = (InUse: true, Array: new ManagedHandle());
|
||||
_pool.Add(newTuple);
|
||||
return newTuple.Array;
|
||||
}
|
||||
|
||||
internal static void Return(ManagedHandle handle)
|
||||
{
|
||||
foreach (ref var tuple in CollectionsMarshal.AsSpan(_pool))
|
||||
{
|
||||
if (tuple.Handle != handle)
|
||||
continue;
|
||||
|
||||
tuple.InUse = false;
|
||||
handle.Target = null;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Exception("Tried to return non-pooled ManagedHandle");
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
Reference in New Issue
Block a user