public override unsafe void Free(void *pointer) { if (pointer == null) { throw new ArgumentException("pointer is null"); } if (!IsOwner(pointer)) { throw new ArgumentException("StackAllocator don't owns the given memory block."); } if (_buffer == null) { throw new InvalidOperationException("StackAllocator have been disposed"); } byte *block = (byte *)pointer; StackAllocatorHeader *header = (StackAllocatorHeader *)(block - sizeof(StackAllocatorHeader)); if (header != _prevOffset) { throw new InvalidOperationException($"Invalid memory block position.\n" + $"Expected memory address: {ToHex(_prevOffset)} but {ToHex(header)} was get.\n" + $"Any memory allocated within the StackAllocator must be free in a LIFO (Last-In First-Out) order."); } _offset -= header->size; _prevOffset -= header->offset; }
public override unsafe void *Allocate(int elementCount, int elementSize = 1, bool initMemory = true) { if (_buffer == null) { throw new InvalidOperationException("StackAllocator have been disposed"); } if (elementCount <= 0) { throw new ArgumentException(elementCount.ToString(), nameof(elementCount)); } if (elementSize <= 0) { throw new ArgumentException(elementSize.ToString(), nameof(elementSize)); } int blockSize = elementCount * elementSize; int size = blockSize + sizeof(StackAllocatorHeader); byte *end = _buffer + _length; byte *nextOffset = _offset + size; if (nextOffset > end) { ThrowOutOfMemory(blockSize); } StackAllocatorHeader *header = (StackAllocatorHeader *)_offset; header->size = blockSize; header->offset = _prevOffset == null ? 0 : (int)(_prevOffset - _buffer); byte *block = _offset + sizeof(StackAllocatorHeader); if (initMemory) { Unsafe.InitBlockUnaligned(block, 0, (uint)blockSize); } _prevOffset = _offset; _offset += size; return(block); }
public override unsafe void *Reallocate(void *pointer, int elementCount, int elementSize = 1, bool initMemory = true) { if (_buffer == null) { throw new InvalidOperationException("StackAllocator have been disposed"); } if (!IsOwner(pointer)) { throw new ArgumentException("StackAllocator don't owns the given memory block."); } if (elementCount <= 0) { throw new ArgumentException(elementCount.ToString(), nameof(elementCount)); } if (elementSize <= 0) { throw new ArgumentException(elementSize.ToString(), nameof(elementSize)); } byte *block = (byte *)pointer; int blockSize = elementCount * elementSize; StackAllocatorHeader *header = (StackAllocatorHeader *)(block - sizeof(StackAllocatorHeader)); if (header->size < blockSize) { return(pointer); } if (header == _prevOffset) { int size = blockSize + sizeof(StackAllocatorHeader); byte *end = _buffer + _length; byte *nextOffset = _offset + size; if (nextOffset > end) { ThrowOutOfMemory(blockSize); } int requiredSize = blockSize - header->size; if (initMemory) { Unsafe.InitBlockUnaligned(_offset, 0, (uint)requiredSize); } header->size = size; _offset = nextOffset; return(block); } else { throw new InvalidOperationException("Only the last allocated memory block can be reallocated.\n" + $"Last memory block was {ToHex(_prevOffset)} but {ToHex(header)} was get."); } }