PkmnLibRSharp/PkmnLibRSharp/Utils/ExternPointer.cs

133 lines
3.3 KiB
C#

using System;
using System.Runtime.CompilerServices;
using PkmnLibSharp.FFI;
[assembly: InternalsVisibleTo("PkmnLibRSharp")]
namespace PkmnLibSharp.Utils
{
public abstract class ExternPointer<TCache> : BasePointer<TCache>
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<TCache> other)
{
return Identifier == other.Identifier;
}
return false;
}
protected bool Equals(ExternPointer<TCache> 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<TCache>? left, ExternPointer<TCache>? right)
{
return Equals(left, right);
}
public static bool operator !=(ExternPointer<TCache>? left, ExternPointer<TCache>? right)
{
return !Equals(left, right);
}
}
}