BEPUutilities2.ResourceManagement.Allocator.IncrementalCompact C# (CSharp) Method

IncrementalCompact() public method

Finds the first allocation with empty space before it and pulls it forward to close the gap. Assumes the ability to perform synchronous reallocation.
public IncrementalCompact ( ulong &id, long &size, long &oldStart, long &newStart ) : bool
id ulong Id of the allocation to be moved, if any.
size long Size of the moved allocation.
oldStart long Old starting location of the allocation.
newStart long New starting location of the allocation.
return bool
        public bool IncrementalCompact(out ulong id, out long size, out long oldStart, out long newStart)
        {
            //Find the allocation nearest to the zero index. Identify it by checking for the previous allocation requiring a wraparound.
            //Start at the beginning of the list since it's marginally more likely to be there than at the end of the list where new allocations get appended.
            for (int i = 0; i < allocations.Count; ++i)
            {
                Allocation previousAllocation;
                allocations.TryGetValue(allocations.Values[i].Previous, out previousAllocation);
                if (previousAllocation.End > allocations.Values[i].Start)
                {
                    //Found the beginning of the list! This index is the first index.
                    //Now, scan forward through the allocation links looking for the first gap.
                    var index = i;
                    var previousEnd = 0L;
                    //Note that we stop before wrapping.
                    for (int iterationIndex = 0; iterationIndex < allocations.Count; ++iterationIndex)
                    {
                        searchStartIndex = index; //If the traversal ends, we want to have this index cached so that the next allocation will start at the end of the contiguous block.
                        Debug.Assert(searchStartIndex >= 0 && searchStartIndex < allocations.Count, "Search start index must be within the allocation set!");
                        if (allocations.Values[index].Start > previousEnd)
                        {
                            //Found a gap.
                            id = allocations.Keys[index];
                            size = allocations.Values[index].End - allocations.Values[index].Start;
                            oldStart = allocations.Values[index].Start;
                            newStart = previousEnd;
                            //Actually perform the move.
                            allocations.Values[index].Start = newStart;
                            allocations.Values[index].End = newStart + size;
                            return true;
                        }
                        //Haven't found a gap yet. Move to the next.
                        previousEnd = allocations.Values[index].End;
                        index = allocations.IndexOf(allocations.Values[index].Next);
                    }
                    break;
                }
            }
            id = 0;
            size = 0;
            oldStart = 0;
            newStart = 0;
            return false;

            //Note: a slightly fancier allocator could 1) track the start and 2) coalesce allocations such that this entire process would become O(1).
            //Something to consider if this allocator ever bottlenecks.
        }