Skip to content

Instantly share code, notes, and snippets.

@raizam
Last active August 16, 2018 11:03
Show Gist options
  • Save raizam/4eb83e806617c30be4115c9784e33478 to your computer and use it in GitHub Desktop.
Save raizam/4eb83e806617c30be4115c9784e33478 to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.InteropServices;
namespace SharpAllocator
{
public struct BufferHeader
{
public uint Head;
public uint Size;
public uint GrowSize;
public uint Capacity;
}
public struct handle<T> where T : unmanaged
{
static Allocator<T> _TAllocator = new Allocator<T>();
}
public unsafe struct Allocator<T> : IDisposable where T : unmanaged
{
private IntPtr ptr;
private BufferHeader* header => (BufferHeader*)ptr; //header data is at position 0
public int ElementSize => sizeof(T);
public Allocator(uint baseSize = 4096 /* physical memory page size */)
{
baseSize += baseSize % 16;
//allocating
this.ptr = Marshal.AllocHGlobal((int)baseSize);
//initialize the header data
var headSize = (uint)Marshal.SizeOf<BufferHeader>();
header->Size = baseSize;
header->GrowSize = baseSize;
//set the head position to the next 16 bit aligned position following the header
header->Head = headSize + (headSize % 16);
}
public uint Alloc(int size)
{
var headPos = header->Head;
//increment head to the next 16bit aligned position
var newHedPos = header->Head + size + (size % 16);
if (newHedPos > header->Size)
{
_grow();
}
return (uint)headPos;
}
private void _grow()
{
//grow buffer
var newSize = header->Size + header->GrowSize;
var newBufferPtr = Marshal.AllocHGlobal((int)newSize);
unchecked
{
for (int offset = 0; offset < header->Size; offset += 8)
{
var val = Marshal.ReadInt64(ptr, offset);
Marshal.WriteInt64(newBufferPtr, offset, val);
}
((BufferHeader*)newBufferPtr)->Size = newSize;
Marshal.FreeHGlobal(ptr); //free old buffer
ptr = newBufferPtr;
}
}
public void Dispose()
{
Marshal.FreeHGlobal(ptr);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment