using System; using System.Collections.Concurrent; using System.Linq; using System.Reflection; namespace PkmnLibSharp.Utilities { public abstract class PointerWrapper : IDisposable { private readonly IntPtr _ptr; internal IntPtr Ptr { get { if (_isDeleted) { throw new Exception( "Pointer access after dispose detected. This is not legal, and will cause native exceptions."); } return _ptr; } } private bool _isDeleted = false; private static readonly ConcurrentDictionary> Cached = new ConcurrentDictionary>(); private protected PointerWrapper() { } protected PointerWrapper(IntPtr ptr) { _ptr = ptr; var weakRef = new WeakReference(this); Cached.AddOrUpdate(ptr, weakRef, (intPtr, reference) => weakRef); } ~PointerWrapper() { if (!_isDeleted) Cached.TryRemove(Ptr, out _); } public static bool TryResolvePointer(IntPtr p, out T result) where T : PointerWrapper { if (Cached.TryGetValue(p, out var val)) { if (val.TryGetTarget(out var target)) { if (target is T r) { result = r; return true; } } } result = null; return false; } protected abstract void DeletePtr(); public virtual void Dispose() { if (_isDeleted) return; Cached.TryRemove(Ptr, out _); DeletePtr(); _isDeleted = true; } protected bool Equals(PointerWrapper other) { return _ptr.Equals(other._ptr); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; return Equals((PointerWrapper) obj); } public override int GetHashCode() { return _ptr.GetHashCode(); } } }