private static long TryAllocateBlocksInSlabs(long totalLength, int maxBlocks, IMemorySlab[] slabs, ref List<IMemoryBlock> allocatedBlocks)
{
allocatedBlocks = new List<IMemoryBlock>();
long minBlockSize;
long allocatedSizeTally = 0;
long largest;
long reqLength;
IMemoryBlock allocdBlock;
int allocdCount = 0;
//TODO: Figure out how to do this math without involving floating point arithmetic
minBlockSize = (long)Math.Ceiling(totalLength / (float)maxBlocks);
do
{
allocdBlock = null;
for (int i = 0; i < slabs.Length; i++)
{
largest = slabs[i].LargestFreeBlockSize;
if (largest >= minBlockSize)
{
//Figure out what length to request for
reqLength = slabs[i].TryAllocate(minBlockSize, totalLength - allocatedSizeTally, out allocdBlock);
if (reqLength > 0)
{
allocatedBlocks.Add(allocdBlock);
allocatedSizeTally += reqLength;
allocdCount++;
if (allocatedSizeTally == totalLength) return allocatedSizeTally;
//Calculate the new minimum block size
//TODO: Figure out how to do this math without involving floating point arithmetic
minBlockSize = (long)Math.Ceiling((totalLength - allocatedSizeTally) / (float)(maxBlocks - allocdCount));
//Scan again from start because there is a chance the smaller minimum block size exists in previously skipped slabs
break;
}
}
}
} while (allocdBlock != null);
return allocatedSizeTally;
}