forked from BilalY/Rasagar
73 lines
3.5 KiB
C#
73 lines
3.5 KiB
C#
|
using System;
|
||
|
using System.Diagnostics;
|
||
|
|
||
|
namespace Unity.Collections.LowLevel.Unsafe
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// A fixed-size buffer from which you can make allocations.
|
||
|
/// </summary>
|
||
|
/// <remarks>Allocations from a scratch allocator are not individually deallocated.
|
||
|
/// Instead, when you're done using all the allocations from a scratch allocator, you dispose the allocator as a whole.</remarks>
|
||
|
[GenerateTestsForBurstCompatibility]
|
||
|
public unsafe struct UnsafeScratchAllocator
|
||
|
{
|
||
|
void* m_Pointer;
|
||
|
int m_LengthInBytes;
|
||
|
readonly int m_CapacityInBytes;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes and returns an instance of UnsafeScratchAllocator.
|
||
|
/// </summary>
|
||
|
/// <param name="ptr">An existing buffer to use as the allocator's internal buffer.</param>
|
||
|
/// <param name="capacityInBytes">The size in bytes of the internal buffer.</param>
|
||
|
public UnsafeScratchAllocator(void* ptr, int capacityInBytes)
|
||
|
{
|
||
|
m_Pointer = ptr;
|
||
|
m_LengthInBytes = 0;
|
||
|
m_CapacityInBytes = capacityInBytes;
|
||
|
}
|
||
|
|
||
|
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")]
|
||
|
void CheckAllocationDoesNotExceedCapacity(ulong requestedSize)
|
||
|
{
|
||
|
if (requestedSize > (ulong)m_CapacityInBytes)
|
||
|
throw new ArgumentException($"Cannot allocate more than provided size in UnsafeScratchAllocator. Requested: {requestedSize} Size: {m_LengthInBytes} Capacity: {m_CapacityInBytes}");
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns an allocation from the allocator's internal buffer.
|
||
|
/// </summary>
|
||
|
/// <param name="sizeInBytes">The size of the new allocation.</param>
|
||
|
/// <param name="alignmentInBytes">The alignment of the new allocation.</param>
|
||
|
/// <returns>A pointer to the new allocation.</returns>
|
||
|
/// <exception cref="ArgumentException">Thrown if the new allocation would exceed the capacity of the allocator.</exception>
|
||
|
public void* Allocate(int sizeInBytes, int alignmentInBytes)
|
||
|
{
|
||
|
if (sizeInBytes == 0)
|
||
|
return null;
|
||
|
var alignmentMask = (ulong)(alignmentInBytes - 1);
|
||
|
var end = (ulong)(IntPtr)m_Pointer + (ulong)m_LengthInBytes;
|
||
|
end = (end + alignmentMask) & ~alignmentMask;
|
||
|
var lengthInBytes = (byte*)(IntPtr)end - (byte*)m_Pointer;
|
||
|
lengthInBytes += sizeInBytes;
|
||
|
CheckAllocationDoesNotExceedCapacity((ulong)lengthInBytes);
|
||
|
m_LengthInBytes = (int)lengthInBytes;
|
||
|
return (void*)(IntPtr)end;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns an allocation from the allocator's internal buffer.
|
||
|
/// </summary>
|
||
|
/// <remarks>The allocation size in bytes is at least `count * sizeof(T)`. The space consumed by the allocation may be a little larger than this size due to alignment.</remarks>
|
||
|
/// <typeparam name="T">The type of element to allocate space for.</typeparam>
|
||
|
/// <param name="count">The number of elements to allocate space for. Defaults to 1.</param>
|
||
|
/// <returns>A pointer to the new allocation.</returns>
|
||
|
/// <exception cref="ArgumentException">Thrown if the new allocation would exceed the capacity of the allocator.</exception>
|
||
|
[GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })]
|
||
|
public void* Allocate<T>(int count = 1) where T : unmanaged
|
||
|
{
|
||
|
return Allocate(UnsafeUtility.SizeOf<T>() * count, UnsafeUtility.AlignOf<T>());
|
||
|
}
|
||
|
}
|
||
|
}
|