public bool Allocate(ulong id, long size, out long outputStart)
{
Debug.Assert(!allocations.ContainsKey(id), "Id must not already be present.");
if (allocations.Count == 0)
{
//If it's the first allocation, then the next and previous pointers should circle around.
if (size <= memoryPoolSize)
{
outputStart = 0;
allocations.Add(id, new Allocation { Start = 0, End = size, Next = id, Previous = id });
searchStartIndex = 0;
return true;
}
outputStart = 0;
return false;
}
Debug.Assert(searchStartIndex >= 0 && searchStartIndex < allocations.Count, "Search start index must be within the allocation set!");
int allocationIndex = searchStartIndex;
var initialId = allocations.Keys[allocationIndex];
while (true)
{
var allocation = allocations.Values[allocationIndex];
int nextAllocationIndex = allocations.IndexOf(allocation.Next);
var nextAllocation = allocations.Values[nextAllocationIndex];
if (nextAllocation.Start < allocation.End)
{
//Wrapped around, so the gap goes from here to the end of the memory block, and from the beginning of the memory block to the next allocation.
//But we need contiguous space so the two areas have to be tested independently.
if (memoryPoolSize - allocation.End >= size)
{
AddAllocation(id, outputStart = allocation.End, allocation.End + size, ref allocations.Values[allocationIndex], ref allocations.Values[nextAllocationIndex]);
return true;
}
else
{
if (nextAllocation.Start >= size)
{
AddAllocation(id, outputStart = 0, size, ref allocations.Values[allocationIndex], ref allocations.Values[nextAllocationIndex]);
return true;
}
}
}
else
{
//The next allocation is in order.
if (nextAllocation.Start - allocation.End >= size)
{
AddAllocation(id, outputStart = allocation.End, allocation.End + size, ref allocations.Values[allocationIndex], ref allocations.Values[nextAllocationIndex]);
return true;
}
}
//If we get here, no open space was found.
//Move on to the next spot.
allocationIndex = nextAllocationIndex;
//Have we already wrapped around?
if (allocations.Keys[allocationIndex] == initialId)
{
//Wrapped around without finding any space.
outputStart = 0;
return false;
}
}
}