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; /// /// The alignment of the memory pointed to by /// private readonly nuint _alignment; /// /// Initializes a new instnace /// /// Pointer to the allocated unmanaged memory /// The size of the unallocated memory block in bytes /// The alignment that the unmanged memory pointed to by /// The that owns the handle being created protected MemoryHandleBase(void* ptr, nuint byteLength, nuint alignment, IUnmanagedMemoryOwner owner) { // Defensive check Debug.Assert(ptr != null, message: "BUG CHECK: E_INVALID_MEMORY_HANDLE"); _ptr = ptr; _bytelen = byteLength; _alignment = alignment; _owner = owner; } /// /// Gets the raw pointer to the unmanaged memory block /// public virtual void* Pointer { get { return _ptr; } } /// /// Returns the memory alignment for the /// public virtual nuint Alignment { get { return _alignment; } } /// /// 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; } } }