feat(memory): refactor allocation and add new queue
Refactored memory management by removing safety checks and introducing `MemoryHandle` for centralized tracking. Simplified allocation logic across allocators and enhanced `Dispose` methods for better resource cleanup. Added `UnsafeChunkedQueue<T>`, a lock-free, dynamically resizing queue with chunk-based memory management, supporting parallel producers and consumers. Updated unit tests to validate new queue functionality and ensure compatibility with refactored memory logic. Incremented assembly version to 1.6.12. BREAKING CHANGE: Removed `#if MHP_ENABLE_SAFETY_CHECKS` blocks, altering memory validation behavior.
This commit is contained in:
@@ -94,27 +94,15 @@ public static unsafe class AllocationManager
|
||||
State = null,
|
||||
Alloc = &Allocate,
|
||||
Realloc = &Reallocate,
|
||||
Free = &Free,
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
IsValid = &IsValid
|
||||
#else
|
||||
IsValid = null
|
||||
#endif
|
||||
Free = &Free
|
||||
};
|
||||
}
|
||||
|
||||
private static void* Allocate(void* _, nuint size, nuint alignment, AllocationOption allocationOption
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
, MemoryHandle* pHandle
|
||||
#endif
|
||||
)
|
||||
private static void* Allocate(void* _, nuint size, nuint alignment, AllocationOption allocationOption)
|
||||
{
|
||||
var ptr = AlignedAlloc(size, alignment);
|
||||
if (ptr == null)
|
||||
{
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
*pHandle = MemoryHandle.Invalid;
|
||||
#endif
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -123,38 +111,12 @@ public static unsafe class AllocationManager
|
||||
MemClear(ptr, size);
|
||||
}
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
*pHandle = AddAllocation(ptr, size);
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private static void* Reallocate(void* _, void* ptr, nuint oldSize, nuint newSize, nuint alignment, AllocationOption allocationOption
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
, MemoryHandle* pHandle
|
||||
#endif
|
||||
)
|
||||
private static void* Reallocate(void* _, void* ptr, nuint oldSize, nuint newSize, nuint alignment, AllocationOption allocationOption)
|
||||
{
|
||||
var newPtr = AlignedRealloc(ptr, newSize, alignment);
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
if (ptr == null && newPtr != null)
|
||||
{
|
||||
AddAllocation(newPtr, newSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newPtr == null)
|
||||
{
|
||||
RemoveAllocation(*pHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateAllocation(*pHandle, newPtr, newSize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (newPtr == null)
|
||||
{
|
||||
return null;
|
||||
@@ -170,16 +132,9 @@ public static unsafe class AllocationManager
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
private static void Free(void* _, void* ptr
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
, MemoryHandle handle
|
||||
#endif
|
||||
)
|
||||
private static void Free(void* _, void* ptr)
|
||||
{
|
||||
AlignedFree(ptr);
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
RemoveAllocation(handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
@@ -332,7 +287,7 @@ public static unsafe class AllocationManager
|
||||
public static VirtualStack.Scope CreateStackScope()
|
||||
{
|
||||
Debug.Assert(s_initialized, "AllocationManager is not initialized.");
|
||||
|
||||
|
||||
EnsureThreadLocalStackInitialize();
|
||||
return t_stackAllocator.Allocator.CreateScope(t_stackAllocator.AllocationHandle);
|
||||
}
|
||||
@@ -373,15 +328,23 @@ public static unsafe class AllocationManager
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
Debug.Assert(s_initialized, "AllocationManager is not initialized.");
|
||||
|
||||
if (s_allocations.TryGetElement(handle.ID, handle.Generation, out var oldInfo))
|
||||
if (newPtr == null)
|
||||
{
|
||||
s_allocations.Remove(handle.ID, handle.Generation);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newInfo = oldInfo with
|
||||
{
|
||||
Address = (IntPtr)newPtr,
|
||||
Size = newSize
|
||||
};
|
||||
|
||||
s_allocations.UpdateElement(handle.ID, handle.Generation, newInfo);
|
||||
if (s_allocations.TryGetElement(handle.ID, handle.Generation, out var oldInfo))
|
||||
{
|
||||
var newInfo = oldInfo with
|
||||
{
|
||||
Address = (IntPtr)newPtr,
|
||||
Size = newSize
|
||||
};
|
||||
|
||||
s_allocations.UpdateElement(handle.ID, handle.Generation, newInfo);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -501,7 +464,6 @@ public static unsafe class AllocationManager
|
||||
if (pStack != null)
|
||||
{
|
||||
pStack->Dispose();
|
||||
Free(pStack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,10 +159,12 @@ public unsafe struct Arena : IMemoryAllocator<Arena, Arena.CreationOptions>
|
||||
return;
|
||||
}
|
||||
|
||||
MemoryUtility.Free(_buffer);
|
||||
var ptr = _buffer;
|
||||
|
||||
_buffer = null;
|
||||
_size = 0;
|
||||
_offset = 0;
|
||||
|
||||
MemoryUtility.Free(ptr);
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,12 @@ public unsafe struct DynamicArena : IMemoryAllocator<DynamicArena, DynamicArena.
|
||||
return;
|
||||
}
|
||||
|
||||
var current = _root;
|
||||
var ptr = _root;
|
||||
|
||||
_root = null;
|
||||
_current = null;
|
||||
|
||||
var current = ptr;
|
||||
while (current != null)
|
||||
{
|
||||
var next = current->next;
|
||||
@@ -191,8 +196,5 @@ public unsafe struct DynamicArena : IMemoryAllocator<DynamicArena, DynamicArena.
|
||||
MemoryUtility.Free(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
_root = null;
|
||||
_current = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,16 +717,6 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
}
|
||||
}
|
||||
|
||||
var chunk = _chunks;
|
||||
while (chunk != null)
|
||||
{
|
||||
var next = chunk->next;
|
||||
AlignedFree(chunk->memory);
|
||||
chunk = next;
|
||||
}
|
||||
|
||||
_chunkArena.Dispose();
|
||||
|
||||
if (_caches != null)
|
||||
{
|
||||
MemoryUtility.Free(_caches);
|
||||
@@ -739,7 +729,17 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
_instanceId = null;
|
||||
}
|
||||
|
||||
var arena = _chunkArena;
|
||||
var chunk = _chunks;
|
||||
_chunks = null;
|
||||
_cacheCount = 0;
|
||||
|
||||
while (chunk != null)
|
||||
{
|
||||
var next = chunk->next;
|
||||
AlignedFree(chunk->memory);
|
||||
chunk = next;
|
||||
}
|
||||
|
||||
arena.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Misaki.HighPerformance.LowLevel.Buffer;
|
||||
|
||||
public readonly struct MemoryHandle : IEquatable<MemoryHandle>
|
||||
public readonly struct MemoryHandle : IDisposable, IEquatable<MemoryHandle>
|
||||
{
|
||||
public readonly int ID
|
||||
{
|
||||
@@ -16,12 +16,25 @@ public readonly struct MemoryHandle : IEquatable<MemoryHandle>
|
||||
|
||||
public static readonly MemoryHandle Invalid = default;
|
||||
|
||||
public bool IsValid => AllocationManager.ContainsAllocation(this);
|
||||
public bool IsInvalid => !IsValid;
|
||||
|
||||
public MemoryHandle(int id, int generation)
|
||||
{
|
||||
ID = id + 1;
|
||||
Generation = generation + 1;
|
||||
}
|
||||
|
||||
public unsafe static MemoryHandle Create(void* address, nuint size)
|
||||
{
|
||||
return AllocationManager.AddAllocation(address, size);
|
||||
}
|
||||
|
||||
public unsafe void Update(void* newAddress, nuint newSize)
|
||||
{
|
||||
AllocationManager.UpdateAllocation(this, newAddress, newSize);
|
||||
}
|
||||
|
||||
public bool Equals(MemoryHandle other)
|
||||
{
|
||||
return ID == other.ID && Generation == other.Generation;
|
||||
@@ -42,6 +55,11 @@ public readonly struct MemoryHandle : IEquatable<MemoryHandle>
|
||||
return $"MemoryHandle(Id: {ID}, Generation: {Generation})";
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
AllocationManager.RemoveAllocation(this);
|
||||
}
|
||||
|
||||
public static bool operator ==(MemoryHandle left, MemoryHandle right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
@@ -61,7 +79,7 @@ public readonly unsafe struct AllocationHandle
|
||||
/// <summary>
|
||||
/// Gets a pointer to the state instance associated with this allocation handle.
|
||||
/// </summary>
|
||||
public void* State
|
||||
public required void* State
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
@@ -69,7 +87,7 @@ public readonly unsafe struct AllocationHandle
|
||||
/// <summary>
|
||||
/// Gets a function pointer for allocating memory.
|
||||
/// </summary>
|
||||
public AllocFunc Alloc
|
||||
public required AllocFunc Alloc
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
@@ -77,7 +95,7 @@ public readonly unsafe struct AllocationHandle
|
||||
/// <summary>
|
||||
/// Gets a function pointer for reallocating memory.
|
||||
/// </summary>
|
||||
public ReallocFunc Realloc
|
||||
public required ReallocFunc Realloc
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
@@ -85,15 +103,7 @@ public readonly unsafe struct AllocationHandle
|
||||
/// <summary>
|
||||
/// Gets a function pointer for freeing allocated memory.
|
||||
/// </summary>
|
||||
public FreeFunc Free
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a function pointer for validating a memory handle.
|
||||
/// </summary>
|
||||
public IsValidFunc IsValid
|
||||
public required FreeFunc Free
|
||||
{
|
||||
get; init;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,10 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
private nuint _size;
|
||||
private nuint _alignment;
|
||||
|
||||
private MemoryHandle _memoryHandle;
|
||||
private AllocationHandle _allocationHandle;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
private readonly MemoryHandle _memoryHandle;
|
||||
#endif
|
||||
private readonly AllocationHandle _allocationHandle;
|
||||
|
||||
public readonly nuint Size => _size;
|
||||
public readonly nuint Alignment => _alignment;
|
||||
@@ -23,14 +25,7 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
if (_buffer != null)
|
||||
{
|
||||
if (_allocationHandle.IsValid != null)
|
||||
{
|
||||
return _allocationHandle.IsValid(_allocationHandle.State, _memoryHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return _memoryHandle.IsValid;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -54,19 +49,12 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
throw new InvalidOperationException("Target allocation handle does not support allocation.");
|
||||
}
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
MemoryHandle memHandle;
|
||||
#endif
|
||||
_buffer = handle.Alloc(handle.State, size, alignment, allocationOption
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
, &memHandle
|
||||
#endif
|
||||
);
|
||||
_buffer = handle.Alloc(handle.State, size, alignment, allocationOption);
|
||||
_size = size;
|
||||
_alignment = alignment;
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_memoryHandle = memHandle;
|
||||
_memoryHandle = MemoryHandle.Create(_buffer, _size);
|
||||
#endif
|
||||
_allocationHandle = handle;
|
||||
}
|
||||
@@ -121,17 +109,10 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
var memHandle = _memoryHandle;
|
||||
#endif
|
||||
_buffer = _allocationHandle.Realloc(_allocationHandle.State, _buffer, _size, newSize, _alignment, option
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
, &memHandle
|
||||
#endif
|
||||
);
|
||||
_buffer = _allocationHandle.Realloc(_allocationHandle.State, _buffer, _size, newSize, _alignment, option);
|
||||
_size = newSize;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_memoryHandle = memHandle;
|
||||
_memoryHandle.Update(_buffer, _size);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -277,44 +258,19 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
{
|
||||
if (!IsCreated)
|
||||
{
|
||||
#if DEBUG
|
||||
if (_buffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var message = "The UnTypedArray is not created or already disposed.";
|
||||
#if MHP_ENABLE_STACKTRACE
|
||||
var stackTrace = new StackTrace(1, true);
|
||||
var sb = new System.Text.StringBuilder();
|
||||
foreach (var frame in stackTrace.GetFrames())
|
||||
{
|
||||
var fileName = frame?.GetFileName();
|
||||
if (frame != null)
|
||||
{
|
||||
var methodInfo = DiagnosticMethodInfo.Create(frame);
|
||||
sb.AppendLine($"File: {fileName}, Type: {methodInfo?.DeclaringTypeName}, Method: {methodInfo?.Name}, Line: {frame.GetFileLineNumber()}");
|
||||
}
|
||||
}
|
||||
|
||||
message += Environment.NewLine + sb.ToString();
|
||||
#endif
|
||||
Debug.WriteLine(message);
|
||||
#endif
|
||||
UnsafeCollectionUtility.ReportDoubleFree<MemoryBlock>(_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_allocationHandle.Free != null)
|
||||
{
|
||||
_allocationHandle.Free(_allocationHandle.State, _buffer
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
, _memoryHandle
|
||||
#endif
|
||||
);
|
||||
_allocationHandle.Free(_allocationHandle.State, _buffer);
|
||||
}
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_memoryHandle.Dispose();
|
||||
#endif
|
||||
|
||||
_buffer = null;
|
||||
_size = 0;
|
||||
_alignment = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Misaki.HighPerformance.LowLevel.Buffer;
|
||||
@@ -14,72 +13,33 @@ public unsafe struct MemoryPool<TAllocator, TOpts> : IDisposable
|
||||
|
||||
public MemoryPool(in TOpts opts)
|
||||
{
|
||||
_pAllocator = (TAllocator*)Malloc((nuint)sizeof(TAllocator));
|
||||
*_pAllocator = TAllocator.Create(opts);
|
||||
var allocator = TAllocator.Create(opts);
|
||||
|
||||
_pAllocator = (TAllocator*)allocator.Allocate((nuint)sizeof(TAllocator), AlignOf<TAllocator>(), AllocationOption.None);
|
||||
*_pAllocator = allocator;
|
||||
|
||||
_allocationHandle = new AllocationHandle
|
||||
{
|
||||
State = _pAllocator,
|
||||
Alloc = &Allocate,
|
||||
Realloc = &Reallocate,
|
||||
Free = &Free,
|
||||
IsValid = null
|
||||
Free = &Free
|
||||
};
|
||||
}
|
||||
|
||||
private static void* Allocate(void* pAllocator, nuint size, nuint alignment, AllocationOption allocationOption
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
, MemoryHandle* pHandle
|
||||
#endif
|
||||
)
|
||||
private static void* Allocate(void* pAllocator, nuint size, nuint alignment, AllocationOption allocationOption)
|
||||
{
|
||||
var ptr = ((TAllocator*)pAllocator)->Allocate(size, alignment, allocationOption);
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
if (ptr != null)
|
||||
{
|
||||
*pHandle = AllocationManager.AddAllocation(ptr, size);
|
||||
}
|
||||
#endif
|
||||
return ptr;
|
||||
return ((TAllocator*)pAllocator)->Allocate(size, alignment, allocationOption);
|
||||
}
|
||||
|
||||
private static void* Reallocate(void* pAllocator, void* ptr, nuint oldSize, nuint newSize, nuint alignment, AllocationOption allocationOption
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
, MemoryHandle* pHandle
|
||||
#endif
|
||||
)
|
||||
private static void* Reallocate(void* pAllocator, void* ptr, nuint oldSize, nuint newSize, nuint alignment, AllocationOption allocationOption)
|
||||
{
|
||||
var newPtr = ((TAllocator*)pAllocator)->Reallocate(ptr, oldSize, newSize, alignment, allocationOption);
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
if (ptr == null && newPtr != null)
|
||||
{
|
||||
*pHandle = AllocationManager.AddAllocation(newPtr, newSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newPtr == null)
|
||||
{
|
||||
AllocationManager.RemoveAllocation(*pHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
AllocationManager.UpdateAllocation(*pHandle, newPtr, newSize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return newPtr;
|
||||
return ((TAllocator*)pAllocator)->Reallocate(ptr, oldSize, newSize, alignment, allocationOption);
|
||||
}
|
||||
|
||||
private static void Free(void* pAllocator, void* ptr
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
, MemoryHandle handle
|
||||
#endif
|
||||
)
|
||||
private static void Free(void* pAllocator, void* ptr)
|
||||
{
|
||||
((TAllocator*)pAllocator)->Free(ptr);
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
AllocationManager.RemoveAllocation(handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -91,8 +51,6 @@ public unsafe struct MemoryPool<TAllocator, TOpts> : IDisposable
|
||||
|
||||
_pAllocator->Dispose();
|
||||
|
||||
MemoryUtility.Free(_pAllocator);
|
||||
|
||||
_pAllocator = null;
|
||||
_allocationHandle = default;
|
||||
}
|
||||
|
||||
@@ -33,9 +33,6 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
_allocator = allocator;
|
||||
_handle = handle;
|
||||
_originalOffset = allocator->_offset;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_allocator->_activeScopeCount++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -43,9 +40,6 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
if (_allocator != null)
|
||||
{
|
||||
_allocator->_offset = _allocator->_offset > _originalOffset ? _originalOffset : _allocator->_offset;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_allocator->_activeScopeCount--;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,9 +47,6 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
private byte* _buffer;
|
||||
private nuint _size;
|
||||
private nuint _offset;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
private uint _activeScopeCount;
|
||||
#endif
|
||||
|
||||
public readonly byte* Buffer => _buffer;
|
||||
public readonly nuint Size => _size;
|
||||
@@ -72,9 +63,6 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
_buffer = (byte*)Malloc(size);
|
||||
_size = size;
|
||||
_offset = 0;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_activeScopeCount = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,13 +89,6 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
/// there is insufficient space in the buffer.</returns>
|
||||
public void* Allocate(nuint size, nuint alignment, AllocationOption allocationOption = AllocationOption.None)
|
||||
{
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
if (_activeScopeCount == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Allocations can only be made within an active memory scope.");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
return null;
|
||||
@@ -197,10 +178,12 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
return;
|
||||
}
|
||||
|
||||
MemoryUtility.Free(_buffer);
|
||||
var ptr = _buffer;
|
||||
|
||||
_buffer = null;
|
||||
_size = 0;
|
||||
_offset = 0;
|
||||
_size = 0;
|
||||
|
||||
MemoryUtility.Free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,6 +474,7 @@ public unsafe struct TLSF : IMemoryAllocator<TLSF, TLSF.CreationOptions>
|
||||
MemoryUtility.Free(_blocks);
|
||||
_blocks = null;
|
||||
}
|
||||
|
||||
if (_slBitmaps != null)
|
||||
{
|
||||
MemoryUtility.Free(_slBitmaps);
|
||||
@@ -481,14 +482,13 @@ public unsafe struct TLSF : IMemoryAllocator<TLSF, TLSF.CreationOptions>
|
||||
}
|
||||
|
||||
MemoryChunk* chunk = _chunks;
|
||||
_chunks = null;
|
||||
|
||||
while (chunk != null)
|
||||
{
|
||||
MemoryChunk* next = chunk->next;
|
||||
AlignedFree(chunk->memory);
|
||||
chunk = next;
|
||||
}
|
||||
|
||||
_chunks = null;
|
||||
_flBitmap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,14 +232,18 @@ public unsafe struct VirtualArena : IMemoryAllocator<VirtualArena, VirtualArena.
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_baseAddress != null)
|
||||
if (_baseAddress == null)
|
||||
{
|
||||
Munmap(_baseAddress, _reserveCapacity);
|
||||
|
||||
_baseAddress = null;
|
||||
_reserveCapacity = 0;
|
||||
_committedSize = 0;
|
||||
_allocatedOffset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
var ptr = _baseAddress;
|
||||
|
||||
_baseAddress = null;
|
||||
_allocatedOffset = 0;
|
||||
_committedSize = 0;
|
||||
_reserveCapacity = 0;
|
||||
|
||||
Munmap(ptr, _reserveCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,6 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
_allocator = allocator;
|
||||
_handle = handle;
|
||||
_originalOffset = allocator->_allocatedOffset;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_allocator->_activeScopeCount++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -40,9 +37,6 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
if (_allocator != null)
|
||||
{
|
||||
_allocator->_allocatedOffset = _allocator->_allocatedOffset > _originalOffset ? _originalOffset : _allocator->_allocatedOffset;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_allocator->_activeScopeCount--;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,9 +45,6 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
private nuint _reserveCapacity;
|
||||
private nuint _committedSize;
|
||||
private nuint _allocatedOffset;
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
private uint _activeScopeCount;
|
||||
#endif
|
||||
|
||||
public readonly byte* Buffer => _baseAddress;
|
||||
public readonly nuint Reserved => _reserveCapacity;
|
||||
@@ -67,10 +58,6 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
_allocatedOffset = 0;
|
||||
|
||||
_baseAddress = (byte*)Mmap(null, _reserveCapacity, VirtualAllocationFlags.Reserve);
|
||||
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
_activeScopeCount = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -100,13 +87,6 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
/// </remarks>
|
||||
public void* Allocate(nuint size, nuint alignment, AllocationOption option = AllocationOption.None)
|
||||
{
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
if (_activeScopeCount == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Allocations can only be made within an active memory scope.");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
return null;
|
||||
@@ -157,13 +137,6 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
|
||||
public void* Reallocate(void* ptr, nuint oldSize, nuint newSize, nuint alignment, AllocationOption allocationOption)
|
||||
{
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
if (_activeScopeCount == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Allocations can only be made within an active memory scope.");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_baseAddress == null)
|
||||
{
|
||||
return null;
|
||||
@@ -237,14 +210,18 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_baseAddress != null)
|
||||
if (_baseAddress == null)
|
||||
{
|
||||
Munmap(_baseAddress, _reserveCapacity);
|
||||
|
||||
_baseAddress = null;
|
||||
_reserveCapacity = 0;
|
||||
_committedSize = 0;
|
||||
_allocatedOffset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
var ptr = _baseAddress;
|
||||
|
||||
_baseAddress = null;
|
||||
_allocatedOffset = 0;
|
||||
_committedSize = 0;
|
||||
_reserveCapacity = 0;
|
||||
|
||||
Munmap(ptr, _reserveCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user