using System.Diagnostics;
using UnmanagedMMU.Allocators;
using UnmanagedMMU.Handles.Internal;
namespace UnmanagedMMU.Handles
{
///
/// Provides a base implementation for typed unmanaged memory handles.
///
///
/// The unmanaged element type stored in the underlying memory block.
///
///
/// This class encapsulates the raw pointer and byte length of an unmanaged
/// memory allocation and provides typed access to that memory.
///
/// Memory lifetime is controlled by the originating allocator; this type
/// does not own or free the underlying memory.
///
internal unsafe abstract class MemoryHandleBase : IMemoryHandle, IOwnedHandle where T : unmanaged
{
///
/// The that owns this handle
///
private readonly IUnmanagedMemoryOwner _owner;
///
/// The raw pointer to the unmanaged memory block
///
private readonly void* _ptr;
///
/// The size of the unmanaged memory block in bytes
///
private readonly nuint _bytelen;
///
/// Indicates whether this has been disposed.
///
private bool _disposed;
///
/// Initializes a new instnace
///
/// Pointer to the allocated unmanaged memory
/// The size of the unallocated memory block in bytes
/// The that owns the handle being created
protected MemoryHandleBase(void* ptr, nuint byteLength, IUnmanagedMemoryOwner owner)
{
// Defensive check
Debug.Assert(ptr != null, message: "BUG CHECK: E_INVALID_MEMORY_HANDLE");
_ptr = ptr;
_bytelen = byteLength;
_owner = owner;
}
///
/// Gets the raw pointer to the unmanaged memory block
///
public virtual void* Pointer
{
get { return _ptr; }
}
///
/// Gets the typed pointer to the unmanged memory block
///
T* IMemoryHandle.Pointer
{
get { return (T*)_ptr; }
}
///
/// Gets the size in bytes of the unmanaged memory block
///
public nuint ByteCount
{
get { return _bytelen; }
}
///
/// Gets the number of elements of type
/// contained in the unmanaged memory block.
///
public nuint Length
{
get { return _bytelen / (nuint)sizeof(T); }
}
///
/// Releases the unmanaged resources held by the .
///
///
/// This method is idempotent and safe to call multiple times. It ensures the underlying
/// memory is cleaned up according to the implementation in .
/// After disposal, the handle is invalid for further use.
///
public void Dispose()
{
if (_disposed)
{
return;
}
_disposed = true;
OnDispose();
GC.SuppressFinalize(this);
}
///
/// Override in derived classes to define lifecycle behavior.
/// This is an abstract method to ensure cleanup logic is always implemented.
///
protected abstract void OnDispose();
///
/// Returns the that created owns this instance
///
/// The that created owns this instance
public IUnmanagedMemoryOwner GetOwner()
{
return _owner;
}
}
}