Handling for caching pointers to userdata objects
This commit is contained in:
parent
ae2080f145
commit
e44432c068
|
@ -16,8 +16,8 @@ namespace PorygonSharp.EvalValues
|
||||||
if (type.IsEnum && !type.IsGenericParameter)
|
if (type.IsEnum && !type.IsGenericParameter)
|
||||||
{
|
{
|
||||||
var typeHash = UserDataHandler.GetTypeId(type);
|
var typeHash = UserDataHandler.GetTypeId(type);
|
||||||
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
var ptr = ObjectEvalValueHandler.GetObjectPtr(o);
|
||||||
return new EvalValue(CreateUserDataEvalValue(typeHash, GCHandle.ToIntPtr(handle)));
|
return new EvalValue(CreateUserDataEvalValue(typeHash, ptr));
|
||||||
}
|
}
|
||||||
var typeCode = Type.GetTypeCode(type);
|
var typeCode = Type.GetTypeCode(type);
|
||||||
switch (typeCode)
|
switch (typeCode)
|
||||||
|
@ -48,8 +48,8 @@ namespace PorygonSharp.EvalValues
|
||||||
throw new Exception($"Type is not registered for use: {type.FullName}");
|
throw new Exception($"Type is not registered for use: {type.FullName}");
|
||||||
}
|
}
|
||||||
var typeHash = UserDataHandler.GetTypeId(type);
|
var typeHash = UserDataHandler.GetTypeId(type);
|
||||||
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
var ptr = ObjectEvalValueHandler.GetObjectPtr(o);
|
||||||
return new EvalValue(CreateUserDataEvalValue(typeHash, GCHandle.ToIntPtr(handle)));
|
return new EvalValue(CreateUserDataEvalValue(typeHash, ptr));
|
||||||
default:
|
default:
|
||||||
throw new Exception($"Type {type} is not currently available as EvalValue");
|
throw new Exception($"Type {type} is not currently available as EvalValue");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace PorygonSharp.EvalValues
|
namespace PorygonSharp.EvalValues
|
||||||
|
@ -21,9 +20,8 @@ namespace PorygonSharp.EvalValues
|
||||||
var valueType = type.IsArray ? type.GetElementType() : type.GetGenericArguments()[0];
|
var valueType = type.IsArray ? type.GetElementType() : type.GetGenericArguments()[0];
|
||||||
if (valueType == null)
|
if (valueType == null)
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
var parentHandle = GCHandle.Alloc(list, GCHandleType.WeakTrackResurrection);
|
ParentCollection = ObjectEvalValueHandler.GetObjectPtr(list);
|
||||||
ParentCollection = GCHandle.ToIntPtr(parentHandle);
|
|
||||||
Getter = Marshal.GetFunctionPointerForDelegate(new GetterDelegate((parent, index) =>
|
Getter = Marshal.GetFunctionPointerForDelegate(new GetterDelegate((parent, index) =>
|
||||||
{
|
{
|
||||||
var val = new EvalValue(index).EvaluateInteger();
|
var val = new EvalValue(index).EvaluateInteger();
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace PorygonSharp.EvalValues
|
||||||
|
{
|
||||||
|
internal static class ObjectEvalValueHandler
|
||||||
|
{
|
||||||
|
private struct PtrObject
|
||||||
|
{
|
||||||
|
public readonly IntPtr Pointer;
|
||||||
|
public readonly WeakReference<object> WeakReference;
|
||||||
|
|
||||||
|
public PtrObject(IntPtr pointer, WeakReference<object> weakReference)
|
||||||
|
{
|
||||||
|
Pointer = pointer;
|
||||||
|
WeakReference = weakReference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Dictionary<int, PtrObject> CreatedPointers = new Dictionary<int, PtrObject>();
|
||||||
|
|
||||||
|
public static IntPtr GetObjectPtr(object o)
|
||||||
|
{
|
||||||
|
var hash = o.GetHashCode();
|
||||||
|
if (CreatedPointers.TryGetValue(hash, out var ptrObject))
|
||||||
|
{
|
||||||
|
if (ptrObject.WeakReference.TryGetTarget(out _))
|
||||||
|
{
|
||||||
|
return ptrObject.Pointer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CreatedPointers.Remove(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
||||||
|
var ptr = GCHandle.ToIntPtr(handle);
|
||||||
|
ptrObject = new PtrObject(ptr, new WeakReference<object>(o));
|
||||||
|
CreatedPointers.Add(o.GetHashCode(), ptrObject);
|
||||||
|
return ptrObject.Pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -160,14 +160,12 @@ namespace PorygonSharp.UserData
|
||||||
if (_implicitCasts.TryGetValue(expectedType, out var func))
|
if (_implicitCasts.TryGetValue(expectedType, out var func))
|
||||||
{
|
{
|
||||||
var castVal = func.Invoke(null, new[] {obj});
|
var castVal = func.Invoke(null, new[] {obj});
|
||||||
var handle = GCHandle.Alloc(castVal, GCHandleType.WeakTrackResurrection);
|
return EvalValueCreator.CreateValue(castVal).GetPointer();
|
||||||
return GCHandle.ToIntPtr(handle);
|
|
||||||
}
|
}
|
||||||
if (_explicitCasts.TryGetValue(expectedType, out func))
|
if (_explicitCasts.TryGetValue(expectedType, out func))
|
||||||
{
|
{
|
||||||
var castVal = func.Invoke(null, new[] {obj});
|
var castVal = func.Invoke(null, new[] {obj});
|
||||||
var handle = GCHandle.Alloc(castVal, GCHandleType.WeakTrackResurrection);
|
return EvalValueCreator.CreateValue(castVal).GetPointer();
|
||||||
return GCHandle.ToIntPtr(handle);
|
|
||||||
}
|
}
|
||||||
throw new Exception("Invalid cast kind");
|
throw new Exception("Invalid cast kind");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue