using System; using System.Runtime.CompilerServices; using PkmnLibSharp.FFI; [assembly: InternalsVisibleTo("PkmnLibRSharp")] namespace PkmnLibSharp.Utils { public abstract class ExternPointer : BasePointer where TCache : class { private bool _isOwner; private bool _isInvalidated; private bool _isDisposed; protected ExternPointer() { } protected ExternPointer(IntPtr ptr, bool isOwner) { InitializePointer(ptr, isOwner); } protected ExternPointer(IdentifiablePointer ptr, bool isOwner) : base(ptr) { _isOwner = isOwner; } protected void InitializePointer(IntPtr ptr, bool isOwner) { InitializePointer(ptr); _isOwner = isOwner; } protected void InitializePointer(IdentifiablePointer ptr, bool isOwner) { InitializePointer(ptr); _isOwner = isOwner; } internal override IntPtr Ptr { get { if (_isInvalidated) { throw new Exception("Pointer was used after invalidate"); } return base.Ptr; } } private IntPtr TakeOwnership() { if (!_isOwner) { throw new Exception("Tried to take ownership of a non-owned object"); } _isOwner = false; return Ptr; } internal IntPtr TakeOwnershipAndInvalidate() { var ptr = TakeOwnership(); Invalidate(); return ptr; } internal void Invalidate() { _isInvalidated = true; CacheHandler.RemoveCache(Identifier); InvalidateChildren(); } public virtual void InvalidateChildren(){} public override void Dispose() { if (_isDisposed) return; if (_isOwner) { InvalidateChildren(); if (!_isInvalidated) Destructor(); _isOwner = false; CacheHandler.RemoveCache(Identifier); } _isDisposed = true; _isInvalidated = true; GC.SuppressFinalize(this); } public override bool Equals(object obj) { if (obj is ExternPointer other) { return Identifier == other.Identifier; } return false; } protected bool Equals(ExternPointer other) { if (Identifier != 0) { return Identifier == other.Identifier; } return Ptr == other.Ptr; } public override int GetHashCode() { if (Identifier != 0) return (int)Identifier; return (int)Ptr; } public static bool operator ==(ExternPointer? left, ExternPointer? right) { return Equals(left, right); } public static bool operator !=(ExternPointer? left, ExternPointer? right) { return !Equals(left, right); } } }