PkmnLibRSharp/PkmnLibRSharp/Utils/ExternPointer.cs

91 lines
2.1 KiB
C#

using System;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("PkmnLibRSharp")]
namespace PkmnLibSharp.Utils
{
public abstract class ExternPointer<TCache> : IDisposable
where TCache : class
{
private IntPtr _ptr;
private bool _isOwner;
private bool _isInvalidated;
private bool _isDisposed;
private TCache? _cache;
protected abstract TCache CreateCache();
internal TCache Cache
{
get { return _cache ??= CacheHandler.GetCache<TCache>(_ptr, CreateCache); }
}
protected ExternPointer()
{
}
protected ExternPointer(IntPtr ptr, bool isOwner)
{
InitializePointer(ptr, isOwner);
}
protected void InitializePointer(IntPtr ptr, bool isOwner)
{
_ptr = ptr;
_isOwner = isOwner;
}
protected abstract void Destructor();
internal IntPtr Ptr
{
get
{
if (_isInvalidated)
{
throw new Exception("Pointer was used after invalidate");
}
return _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;
}
private void Invalidate()
{
_isInvalidated = true;
CacheHandler.RemoveCache(_ptr);
}
public void Dispose()
{
if (_isDisposed)
return;
if (_isOwner)
{
if (!_isInvalidated)
Destructor();
_isOwner = false;
CacheHandler.RemoveCache(_ptr);
}
_isDisposed = true;
_isInvalidated = true;
}
}
}