Updated the SegmentedPool to allow for zeroing of allocations and for returning a pointer to allocated memory to allow for use in unsafe structs (#2)

This commit was merged in pull request #2.
This commit is contained in:
Jim
2026-03-20 17:51:15 +00:00
parent dfbdf905fe
commit c2150acb2c
15 changed files with 2788 additions and 674 deletions

View File

@@ -0,0 +1,126 @@
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>
/// 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="owner">The <see cref="IUnmanagedMemoryOwner"/> that owns the <see cref="MemoryHandleBase{T}"/> handle being created</param>
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;
}
/// <summary>
/// Gets the raw pointer to the unmanaged memory block
/// </summary>
public virtual void* Pointer
{
get { return _ptr; }
}
/// <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;
}
}
}