Improved SegmentedPool with the introduction of handles and alignment (#1)
This commit is contained in:
27
UnmangedMMU/Handles/IMemoryHandle.cs
Normal file
27
UnmangedMMU/Handles/IMemoryHandle.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using UnmanagedMMU.Allocators;
|
||||
|
||||
namespace UnmanagedMMU.Handles
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Interface that represents an untyped handle to unmanaged memory.
|
||||
/// </summary>
|
||||
public unsafe interface IMemoryHandle
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw pointer to the underlying unmanaged memory block.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The returned pointer is valid only for the lifetime of the allocator
|
||||
/// that created this <see cref="IMemoryHandle"/>.
|
||||
/// </remarks>
|
||||
void* Pointer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bytes in the unmanaged memory block
|
||||
/// represented by this <see cref="IMemoryHandle"/>.
|
||||
/// </summary>
|
||||
nuint ByteCount { get; }
|
||||
}
|
||||
}
|
||||
34
UnmangedMMU/Handles/IMemoryHandleT.cs
Normal file
34
UnmangedMMU/Handles/IMemoryHandleT.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using UnmanagedMMU.Allocators;
|
||||
|
||||
namespace UnmanagedMMU.Handles
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Interface that represents a typed handle to unmanaged memory.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// The unmanaged element type stored in the underlying memory block.
|
||||
/// </typeparam>
|
||||
public unsafe interface IMemoryHandle<T> : IMemoryHandle, IDisposable where T : unmanaged
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets the typed <typeparamref name="T"/> pointer to the underlying unmanaged memory block.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The pointer becomes invalid after the handle is disposed.
|
||||
/// </remarks>
|
||||
new T* Pointer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of elements contained in this handle.
|
||||
/// </summary>
|
||||
nuint Length { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the underlying unmanaged memory block held by this handle back to the owning <see cref="IUnmanagedMemoryOwner"/> instance
|
||||
/// </summary>
|
||||
new void Dispose() { }
|
||||
}
|
||||
}
|
||||
15
UnmangedMMU/Handles/Internal/IOwnedHandle.cs
Normal file
15
UnmangedMMU/Handles/Internal/IOwnedHandle.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using UnmanagedMMU.Allocators;
|
||||
|
||||
namespace UnmanagedMMU.Handles.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface defining an interface for handle ownership semantics
|
||||
/// </summary>
|
||||
internal interface IOwnedHandle: IMemoryHandle
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the <see cref="IUnmanagedMemoryOwner"/> that created owns this <see cref="IOwnedHandle"/>
|
||||
/// </summary>
|
||||
IUnmanagedMemoryOwner GetOwner();
|
||||
}
|
||||
}
|
||||
126
UnmangedMMU/Handles/MemoryHandleBase.cs
Normal file
126
UnmangedMMU/Handles/MemoryHandleBase.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
UnmangedMMU/Handles/PersistentMemoryHandle.cs
Normal file
21
UnmangedMMU/Handles/PersistentMemoryHandle.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using UnmanagedMMU.Allocators;
|
||||
|
||||
namespace UnmanagedMMU.Handles
|
||||
{
|
||||
internal sealed unsafe class PersistentMemoryHandle<T> : MemoryHandleBase<T> where T : unmanaged
|
||||
{
|
||||
|
||||
public PersistentMemoryHandle(void* ptr, nuint byteLength, IUnmanagedMemoryOwner owner) : base(ptr, byteLength, owner)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnDispose()
|
||||
{
|
||||
if (Pointer != null)
|
||||
{
|
||||
GetOwner().Free(this);
|
||||
// No need to set _ptr = null here; MemoryHandleBase._disposed flag prevents double-free
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
UnmangedMMU/Handles/SegmentedMemoryHandle.cs
Normal file
21
UnmangedMMU/Handles/SegmentedMemoryHandle.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnmanagedMMU.Allocators;
|
||||
|
||||
namespace UnmanagedMMU.Handles
|
||||
{
|
||||
internal sealed unsafe class SegmentedMemoryHandle<T> : MemoryHandleBase<T> where T : unmanaged
|
||||
{
|
||||
public SegmentedMemoryHandle(void* ptr, nuint byteLength, IUnmanagedMemoryOwner owner) : base(ptr, byteLength, owner)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnDispose()
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user