Add TLSF allocator and refactor allocation API
- Introduced TLSF allocator with thread-safe wrapper and integrated into AllocationManager. - Extended AllocationManagerDesc for TLSF config; made properties settable. - Refactored AllocationHandle to encapsulate function pointers and state, replacing direct field access with methods. - Updated all memory-related structs to use new AllocationHandle API. - Added ReplaceIfZeros utility to MemoryUtility. - Improved IndexOfNullByte performance. - Minor fix in MemoryLeakException output order. - FreeList now uses a fixed 64KB refill budget. - Bumped version to 1.6.21; removed MHP_ENABLE_STACKTRACE from Debug. - Updated Program.cs to test TLSF allocator and manage allocation lifecycle.
This commit is contained in:
@@ -251,7 +251,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
||||
throw new InvalidOperationException("Target allocation handle does not support allocation.");
|
||||
}
|
||||
|
||||
var buf = (byte*)_allocationHandle.Alloc(_allocationHandle.State, (uint)totalSize, (nuint)_alignment, allocationOption);
|
||||
var buf = (byte*)_allocationHandle.Alloc((uint)totalSize, (nuint)_alignment, allocationOption);
|
||||
|
||||
_buffer = buf;
|
||||
_keys = (TKey*)(_buffer + keyOffset);
|
||||
@@ -287,7 +287,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
||||
|
||||
if (_allocationHandle.Free != null)
|
||||
{
|
||||
_allocationHandle.Free(_allocationHandle.State, oldBuffer);
|
||||
_allocationHandle.Free(oldBuffer);
|
||||
}
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
@@ -707,7 +707,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
|
||||
|
||||
if (_allocationHandle.Free != null)
|
||||
{
|
||||
_allocationHandle.Free(_allocationHandle.State, _buffer);
|
||||
_allocationHandle.Free(_buffer);
|
||||
}
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
|
||||
@@ -141,7 +141,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
throw new InvalidOperationException("Target allocation handle does not support allocation.");
|
||||
}
|
||||
|
||||
_buffer = (T*)handle.Alloc(handle.State, (nuint)(count * sizeof(T)), AlignOf<T>(), allocationOption);
|
||||
_buffer = (T*)handle.Alloc((nuint)(count * sizeof(T)), AlignOf<T>(), allocationOption);
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_memoryHandle = MemoryHandle.Create(_buffer, (nuint)(count * sizeof(T)));
|
||||
#endif
|
||||
@@ -232,7 +232,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
}
|
||||
|
||||
var elemSize = SizeOf<T>();
|
||||
_buffer = (T*)_allocationHandle.Realloc(_allocationHandle.State, _buffer, (nuint)Count * elemSize, (nuint)newSize * elemSize, AlignOf<T>(), option);
|
||||
_buffer = (T*)_allocationHandle.Realloc(_buffer, (nuint)Count * elemSize, (nuint)newSize * elemSize, AlignOf<T>(), option);
|
||||
_count = newSize;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_memoryHandle.Update(_buffer, (nuint)newSize * elemSize);
|
||||
@@ -388,10 +388,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
|
||||
return;
|
||||
}
|
||||
|
||||
if (_allocationHandle.Free != null)
|
||||
{
|
||||
_allocationHandle.Free(_allocationHandle.State, _buffer);
|
||||
}
|
||||
_allocationHandle.Free(_buffer);
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_memoryHandle.Dispose();
|
||||
|
||||
@@ -70,7 +70,7 @@ public unsafe struct UnsafeParallelHashMap<TKey, TValue> : IDisposable
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(capacity);
|
||||
|
||||
_data = (UnsafeParallelHashMapData<TKey, TValue>*)handle.Alloc(handle.State, (uint)sizeof(UnsafeParallelHashMapData<TKey, TValue>), (nuint)AlignOf<UnsafeParallelHashMapData<TKey, TValue>>(), AllocationOption.Clear);
|
||||
_data = (UnsafeParallelHashMapData<TKey, TValue>*)handle.Alloc((uint)sizeof(UnsafeParallelHashMapData<TKey, TValue>), (nuint)AlignOf<UnsafeParallelHashMapData<TKey, TValue>>(), AllocationOption.Clear);
|
||||
|
||||
if (_data == null)
|
||||
throw new OutOfMemoryException("Failed to allocate UnsafeParallelHashMapData.");
|
||||
@@ -110,13 +110,13 @@ public unsafe struct UnsafeParallelHashMap<TKey, TValue> : IDisposable
|
||||
|
||||
if (_data->buffer != null && _data->allocationHandle.Free != null)
|
||||
{
|
||||
_data->allocationHandle.Free(_data->allocationHandle.State, _data->buffer);
|
||||
_data->allocationHandle.Free(_data->buffer);
|
||||
_data->buffer = null;
|
||||
}
|
||||
|
||||
if (_data != null && _data->allocationHandle.Free != null)
|
||||
{
|
||||
_data->allocationHandle.Free(_data->allocationHandle.State, _data);
|
||||
_data->allocationHandle.Free(_data);
|
||||
_data = null;
|
||||
}
|
||||
}
|
||||
@@ -186,7 +186,7 @@ public unsafe struct UnsafeParallelHashMap<TKey, TValue> : IDisposable
|
||||
throw new InvalidOperationException("Target allocation handle does not support allocation.");
|
||||
}
|
||||
|
||||
var buf = (byte*)data->allocationHandle.Alloc(data->allocationHandle.State, (uint)totalSize, (nuint)data->alignment, allocationOption);
|
||||
var buf = (byte*)data->allocationHandle.Alloc((uint)totalSize, (nuint)data->alignment, allocationOption);
|
||||
|
||||
data->buffer = buf;
|
||||
data->keys = (TKey*)(buf + keyOffset);
|
||||
@@ -399,7 +399,7 @@ public unsafe struct UnsafeParallelHashMap<TKey, TValue> : IDisposable
|
||||
|
||||
if (_data->allocationHandle.Free != null && oldBuffer != null)
|
||||
{
|
||||
_data->allocationHandle.Free(_data->allocationHandle.State, oldBuffer);
|
||||
_data->allocationHandle.Free(oldBuffer);
|
||||
}
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
|
||||
@@ -88,7 +88,7 @@ public unsafe struct UnsafeParallelQueue<T> : IDisposable
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static DisposablePtr<UnsafeParallelQueue<T>> Allocate(int capacityPerChunk, AllocationHandle handle, AllocationOption allocationOption = AllocationOption.None)
|
||||
{
|
||||
var pQueue = (UnsafeParallelQueue<T>*)handle.Alloc(handle.State, SizeOf<DisposablePtr<UnsafeParallelQueue<T>>>(), AlignOf<DisposablePtr<UnsafeParallelQueue<T>>>(), AllocationOption.None);
|
||||
var pQueue = (UnsafeParallelQueue<T>*)handle.Alloc(SizeOf<DisposablePtr<UnsafeParallelQueue<T>>>(), AlignOf<DisposablePtr<UnsafeParallelQueue<T>>>(), AllocationOption.None);
|
||||
*pQueue = new UnsafeParallelQueue<T>(capacityPerChunk, handle, allocationOption);
|
||||
return new DisposablePtr<UnsafeParallelQueue<T>>(pQueue);
|
||||
}
|
||||
@@ -289,7 +289,7 @@ public unsafe struct UnsafeParallelQueue<T> : IDisposable
|
||||
private readonly ChunkHeader* AllocateNewChunk()
|
||||
{
|
||||
nuint byteSize = (nuint)sizeof(ChunkHeader) + (nuint)(_chunkCapacity * sizeof(ChunkSlot));
|
||||
ChunkHeader* block = (ChunkHeader*)_allocHandle.Alloc(_allocHandle.State, byteSize, AlignOf<int>(), _allocOption);
|
||||
ChunkHeader* block = (ChunkHeader*)_allocHandle.Alloc(byteSize, AlignOf<int>(), _allocOption);
|
||||
|
||||
block->next = null;
|
||||
block->nextFree = null;
|
||||
@@ -352,7 +352,7 @@ public unsafe struct UnsafeParallelQueue<T> : IDisposable
|
||||
while (curr != null)
|
||||
{
|
||||
var next = curr->next;
|
||||
_allocHandle.Free(_allocHandle.State, curr);
|
||||
_allocHandle.Free(curr);
|
||||
curr = next;
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ public unsafe struct UnsafeParallelQueue<T> : IDisposable
|
||||
while (free != null)
|
||||
{
|
||||
var next = free->nextFree;
|
||||
_allocHandle.Free(_allocHandle.State, free);
|
||||
_allocHandle.Free(free);
|
||||
free = next;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user