PkmnLibSharp/PkmnLibSharp/Utilities/PointerWrapper.cs

96 lines
2.4 KiB
C#

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<IntPtr, WeakReference<object>> Cached =
new ConcurrentDictionary<IntPtr, WeakReference<object>>();
private protected PointerWrapper()
{
}
protected PointerWrapper(IntPtr ptr)
{
_ptr = ptr;
var weakRef = new WeakReference<object>(this);
Cached.AddOrUpdate(ptr, weakRef, (intPtr, reference) => weakRef);
}
~PointerWrapper()
{
if (!_isDeleted)
Cached.TryRemove(Ptr, out _);
}
public static bool TryResolvePointer<T>(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();
}
}
}