public byte *Allocate(int bytesToAllocate, int alignment) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (bytesToAllocate > ms_BlockSize) { throw new ArgumentException($"Cannot allocate more than {ms_BlockSize} in BlockAllocator. Requested: {bytesToAllocate}"); } #endif var nextByteOffsetAligned = (m_nextByteOffset + alignment - 1) & ~(alignment - 1); var nextBlockSize = nextByteOffsetAligned + bytesToAllocate; if (m_blocks.Length == 0 || nextBlockSize > ms_BlockSize) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (m_blocks.Length == m_blocks.Capacity) { throw new ArgumentException($"Cannot exceed budget of {ms_BudgetInBytes} in BlockAllocator."); } #endif // Allocate a fresh block of memory m_blocks.Add((byte *)AllocatorManager.Allocate(m_handle, sizeof(byte), ms_BlockAlignment, ms_BlockSize)); m_allocations.Add(0); nextByteOffsetAligned = 0; } var blockIndex = m_blocks.Length - 1; var pointer = (byte *)m_blocks[blockIndex] + nextByteOffsetAligned; m_nextByteOffset = nextByteOffsetAligned + bytesToAllocate; m_allocations.Ptr[blockIndex]++; return(pointer); }
/// <summary> /// Constructs an allocator. /// </summary> /// <param name="budgetInBytes">Budget of the allocator in bytes.</param> /// <param name="bufferSizeInBytes">Size of each buffer to be allocated in bytes.</param> /// <param name="handle">An AllocatorHandle to use for internal bookkeeping structures.</param> /// <exception cref="InvalidOperationException">Thrown if the allocator cannot reserve the address range required for the given budget.</exception> public BufferAllocator(int budgetInBytes, int bufferSizeInBytes, AllocatorManager.AllocatorHandle handle) { BufferSizeInBytes = bufferSizeInBytes; // Reserve the entire budget's worth of address space. The reserved space may be larger than the budget // due to page sizes. var pageCount = VirtualMemoryUtility.BytesToPageCount((uint)budgetInBytes, VirtualMemoryUtility.DefaultPageSizeInBytes); BaselibErrorState errorState; ReservedRange = VirtualMemoryUtility.ReserveAddressSpace(pageCount, VirtualMemoryUtility.DefaultPageSizeInBytes, out errorState); #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!errorState.Success) { throw new InvalidOperationException($"Failed to reserve address range for {budgetInBytes} bytes"); } #endif // Init a free list of blocks. MaxBufferCount = (int)VirtualMemoryUtility.BytesToPageCount((uint)budgetInBytes, (uint)bufferSizeInBytes); FreeList = new UnsafeIntList(MaxBufferCount, handle); for (int i = MaxBufferCount - 1; i >= 0; --i) { FreeList.Add(i); } }
public static bool AddReaderTypeIndex(int typeIndex, ref UnsafeIntList reading, ref UnsafeIntList writing) { if (reading.Contains(typeIndex)) { return(false); } if (writing.Contains(typeIndex)) { return(false); } reading.Add(typeIndex); return(true); }
public BlockAllocator(AllocatorManager.AllocatorHandle handle, int budgetInBytes) { m_bufferAllocator = new BufferAllocator(budgetInBytes, ms_BlockSize, handle); m_nextPtr = 0; var blocks = (budgetInBytes + ms_BlockSize - 1) >> ms_Log2BlockSize; m_allocations = new UnsafeIntList(blocks, handle); for (int i = 0; i < blocks; ++i) { m_allocations.Add(0); } m_currentBlockIndex = -1; }
public static bool AddWriterTypeIndex(int typeIndex, ref UnsafeIntList reading, ref UnsafeIntList writing) { if (writing.Contains(typeIndex)) { return(false); } var readingIndex = reading.IndexOf(typeIndex); if (readingIndex != -1) { reading.RemoveAtSwapBack(readingIndex); } writing.Add(typeIndex); return(true); }
/// <summary> /// Frees the buffer represented by the given index. /// </summary> /// <param name="index">Index to buffer.</param> /// <exception cref="ArgumentException">Thrown when index is less than zero or when greater than or equal to BufferCapacity</exception> /// <exception cref="InvalidOperationException">Thrown if the buffer cannot be decommitted.</exception> public void Free(int index) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (index < 0 || index >= BufferCapacity) { throw new ArgumentException($"Cannot free index {index}, it is outside the expected range [0, {BufferCapacity})."); } #endif BaselibErrorState errorState; var range = new VMRange((IntPtr)this[index], (uint)BufferSizeInBytes, VirtualMemoryUtility.DefaultPageSizeInBytes); VirtualMemoryUtility.DecommitMemory(range, out errorState); if (!errorState.Success) { #if ENABLE_UNITY_COLLECTIONS_CHECKS throw new InvalidOperationException($"Failed to decommit address range {range}."); #endif } FreeList.Add(index); }
public byte *Allocate(int bytesToAllocate, int alignment) { CheckAllocationToLarge(bytesToAllocate); var nextByteOffsetAligned = (m_nextByteOffset + alignment - 1) & ~(alignment - 1); var nextBlockSize = nextByteOffsetAligned + bytesToAllocate; if (m_blocks.Length == 0 || nextBlockSize > ms_BlockSize) { CheckExceededBudget(); // Allocate a fresh block of memory m_blocks.Add(AllocatorManager.Allocate(m_handle, sizeof(byte), ms_BlockAlignment, ms_BlockSize)); m_allocations.Add(0); nextByteOffsetAligned = 0; } var blockIndex = m_blocks.Length - 1; var pointer = (byte *)m_blocks[blockIndex] + nextByteOffsetAligned; m_nextByteOffset = nextByteOffsetAligned + bytesToAllocate; m_allocations.Ptr[blockIndex]++; return(pointer); }