A game about forced loneliness, made by TACStudios
at master 72 lines 3.6 kB view raw
1using System; 2using System.Diagnostics; 3 4namespace Unity.Collections.LowLevel.Unsafe 5{ 6 /// <summary> 7 /// A fixed-size buffer from which you can make allocations. 8 /// </summary> 9 /// <remarks>Allocations from a scratch allocator are not individually deallocated. 10 /// Instead, when you're done using all the allocations from a scratch allocator, you dispose the allocator as a whole.</remarks> 11 [GenerateTestsForBurstCompatibility] 12 public unsafe struct UnsafeScratchAllocator 13 { 14 void* m_Pointer; 15 int m_LengthInBytes; 16 readonly int m_CapacityInBytes; 17 18 /// <summary> 19 /// Initializes and returns an instance of UnsafeScratchAllocator. 20 /// </summary> 21 /// <param name="ptr">An existing buffer to use as the allocator's internal buffer.</param> 22 /// <param name="capacityInBytes">The size in bytes of the internal buffer.</param> 23 public UnsafeScratchAllocator(void* ptr, int capacityInBytes) 24 { 25 m_Pointer = ptr; 26 m_LengthInBytes = 0; 27 m_CapacityInBytes = capacityInBytes; 28 } 29 30 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] 31 void CheckAllocationDoesNotExceedCapacity(ulong requestedSize) 32 { 33 if (requestedSize > (ulong)m_CapacityInBytes) 34 throw new ArgumentException($"Cannot allocate more than provided size in UnsafeScratchAllocator. Requested: {requestedSize} Size: {m_LengthInBytes} Capacity: {m_CapacityInBytes}"); 35 } 36 37 /// <summary> 38 /// Returns an allocation from the allocator's internal buffer. 39 /// </summary> 40 /// <param name="sizeInBytes">The size of the new allocation.</param> 41 /// <param name="alignmentInBytes">The alignment of the new allocation.</param> 42 /// <returns>A pointer to the new allocation.</returns> 43 /// <exception cref="ArgumentException">Thrown if the new allocation would exceed the capacity of the allocator.</exception> 44 public void* Allocate(int sizeInBytes, int alignmentInBytes) 45 { 46 if (sizeInBytes == 0) 47 return null; 48 var alignmentMask = (ulong)(alignmentInBytes - 1); 49 var end = (ulong)(IntPtr)m_Pointer + (ulong)m_LengthInBytes; 50 end = (end + alignmentMask) & ~alignmentMask; 51 var lengthInBytes = (byte*)(IntPtr)end - (byte*)m_Pointer; 52 lengthInBytes += sizeInBytes; 53 CheckAllocationDoesNotExceedCapacity((ulong)lengthInBytes); 54 m_LengthInBytes = (int)lengthInBytes; 55 return (void*)(IntPtr)end; 56 } 57 58 /// <summary> 59 /// Returns an allocation from the allocator's internal buffer. 60 /// </summary> 61 /// <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> 62 /// <typeparam name="T">The type of element to allocate space for.</typeparam> 63 /// <param name="count">The number of elements to allocate space for. Defaults to 1.</param> 64 /// <returns>A pointer to the new allocation.</returns> 65 /// <exception cref="ArgumentException">Thrown if the new allocation would exceed the capacity of the allocator.</exception> 66 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 67 public void* Allocate<T>(int count = 1) where T : unmanaged 68 { 69 return Allocate(UnsafeUtility.SizeOf<T>() * count, UnsafeUtility.AlignOf<T>()); 70 } 71 } 72}