142 lines
4.9 KiB
C#
142 lines
4.9 KiB
C#
using System.Diagnostics;
|
|
using UnmanagedMMU.Allocators;
|
|
using UnmanagedMMU.Handles.Internal;
|
|
|
|
namespace UnmanagedMMU.Handles
|
|
{
|
|
|
|
/// <summary>
|
|
/// Provides a base implementation for typed unmanaged memory handles.
|
|
/// </summary>
|
|
/// <typeparam name="T">
|
|
/// The unmanaged element type stored in the underlying memory block.
|
|
/// </typeparam>
|
|
/// <remarks>
|
|
/// 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.
|
|
/// </remarks>
|
|
internal unsafe abstract class MemoryHandleBase<T> : IMemoryHandle<T>, IOwnedHandle where T : unmanaged
|
|
{
|
|
|
|
/// <summary>
|
|
/// The <see cref="IUnmanagedMemoryOwner"/> that owns this <see cref="MemoryHandleBase{T}"/> handle
|
|
/// </summary>
|
|
private readonly IUnmanagedMemoryOwner _owner;
|
|
|
|
/// <summary>
|
|
/// The raw pointer to the unmanaged memory block
|
|
/// </summary>
|
|
private readonly void* _ptr;
|
|
|
|
/// <summary>
|
|
/// The size of the unmanaged memory block in bytes
|
|
/// </summary>
|
|
private readonly nuint _bytelen;
|
|
|
|
/// <summary>
|
|
/// Indicates whether this <see cref="MemoryHandleBase{T}"/> has been disposed.
|
|
/// </summary>
|
|
private bool _disposed;
|
|
|
|
/// <summary>
|
|
/// The alignment of the memory pointed to by <see cref="_ptr"/>
|
|
/// </summary>
|
|
private readonly nuint _alignment;
|
|
|
|
/// <summary>
|
|
/// Initializes a new <see cref="MemoryHandleBase{T}"/> instnace
|
|
/// </summary>
|
|
/// <param name="ptr">Pointer to the allocated unmanaged memory</param>
|
|
/// <param name="byteLength">The size of the unallocated memory block in bytes</param>
|
|
/// <param name="alignment">The alignment that the unmanged memory pointed to by <paramref name="ptr"/> </param>
|
|
/// <param name="owner">The <see cref="IUnmanagedMemoryOwner"/> that owns the <see cref="MemoryHandleBase{T}"/> handle being created</param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the raw pointer to the unmanaged memory block
|
|
/// </summary>
|
|
public virtual void* Pointer
|
|
{
|
|
get { return _ptr; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the memory alignment for the <see cref="MemoryHandleBase{T}"/>
|
|
/// </summary>
|
|
public virtual nuint Alignment
|
|
{
|
|
get { return _alignment; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the typed pointer to the unmanged memory block
|
|
/// </summary>
|
|
T* IMemoryHandle<T>.Pointer
|
|
{
|
|
get { return (T*)_ptr; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the size in bytes of the unmanaged memory block
|
|
/// </summary>
|
|
public nuint ByteCount
|
|
{
|
|
get { return _bytelen; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the number of elements of type <typeparamref name="T"/>
|
|
/// contained in the unmanaged memory block.
|
|
/// </summary>
|
|
public nuint Length
|
|
{
|
|
get { return _bytelen / (nuint)sizeof(T); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Releases the unmanaged resources held by the <see cref="MemoryHandleBase{T}"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method is idempotent and safe to call multiple times. It ensures the underlying
|
|
/// memory is cleaned up according to the implementation in <see cref="OnDispose()"/>.
|
|
/// After disposal, the handle is invalid for further use.
|
|
/// </remarks>
|
|
public void Dispose()
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
_disposed = true;
|
|
OnDispose();
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override in derived classes to define lifecycle behavior.
|
|
/// This is an abstract method to ensure cleanup logic is always implemented.
|
|
/// </summary>
|
|
protected abstract void OnDispose();
|
|
|
|
/// <summary>
|
|
/// Returns the <see cref="IUnmanagedMemoryOwner"/> that created owns this <see cref="MemoryHandleBase{T}"/> instance
|
|
/// </summary>
|
|
/// <returns>The <see cref="IUnmanagedMemoryOwner"/> that created owns this <see cref="MemoryHandleBase{T}"/> instance</returns>
|
|
public IUnmanagedMemoryOwner GetOwner()
|
|
{
|
|
return _owner;
|
|
}
|
|
}
|
|
}
|