Handling for caching pointers to userdata objects
This commit is contained in:
		| @@ -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 | ||||||
| @@ -22,8 +21,7 @@ namespace PorygonSharp.EvalValues | |||||||
|             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(); | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								PorygonSharp/EvalValues/ObjectEvalValueHandler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								PorygonSharp/EvalValues/ObjectEvalValueHandler.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -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"); | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user