private void assureFreeMemoryByStartAccumulation(long bytes) { MemoryBlockByAddress freeBlock = new MemoryBlockByAddress(-1L, 0L); int removedBlocks = 0; foreach (MemoryBlockByAddress block in this.structureByAddress) { if (freeBlock.Address < 0L) { freeBlock = block; removedBlocks++; continue; } long occupiedBytes = block.Address - freeBlock.End; if (occupiedBytes < 0) { throw new InvalidOperationException("Allocated memory is overlapping."); } if (occupiedBytes == 0) { freeBlock.Size += block.Size; } else { this.memoryMove(freeBlock.End, freeBlock.Address, occupiedBytes); MemoryBlockByAddress foundNode; int startIndex = this.allocationsByAddress.GetLeftmostGreaterOrEqualIndex(new MemoryBlockByAddress(freeBlock.End, 0L), out foundNode); int endIndexExclusive = this.allocationsByAddress.GetLeftmostGreaterOrEqualIndex(new MemoryBlockByAddress(block.Address, 0L), out foundNode); long delta = freeBlock.Size; for (int i = endIndexExclusive; --i >= startIndex;) { this.allocationsByAddress[i].Address -= delta; } freeBlock = new MemoryBlockByAddress(block.Address - freeBlock.Size, block.Size + freeBlock.Size); } removedBlocks++; if (freeBlock.Size >= bytes) { break; } } for (int i = removedBlocks; --i >= 0;) { MemoryBlockBySize blockBySize = this.structureByAddress[i].ToSize; this.structureBySize.Remove(blockBySize); this.structureByAddress.RemoveAt(i); } this.structureByAddress.Add(freeBlock); this.structureBySize.Add(freeBlock.ToSize); }
private void assureFreeMemoryByMinimumMemoryCopy(long bytes) { int n = this.structureByAddress.Count; MemoryRange[] memory = new MemoryRange[n]; int storeIndex = 0; long lastPointer = 0L, totalFreeSoFar = 0L, totalCostSoFar = 0L; foreach (MemoryBlockByAddress block in this.structureByAddress) { long occupiedBytes = block.Address - lastPointer; totalFreeSoFar += block.Size; totalCostSoFar += occupiedBytes; memory[storeIndex++] = new MemoryRange(totalFreeSoFar, totalCostSoFar); lastPointer = block.End; } if (totalFreeSoFar != this.free) { throw new InvalidOperationException("Free memory mismatch."); } int startIndex = -1, endIndex = -1; long maxFreeBlockCost = long.MaxValue; int j = memory.BinarySearchLeftmostGreaterOrEqual(bytes, mr => mr.TotalFreeBytes); for (int i = 0; i < n && j < n; i++) { long cost = memory[j].TotalCost - memory[i].TotalCost; long freeBytes = memory[j].TotalFreeBytes - (i == 0 ? 0L : memory[i - 1].TotalFreeBytes); if (freeBytes >= bytes && cost < maxFreeBlockCost) { startIndex = i; endIndex = j; maxFreeBlockCost = cost; } while (j < n && memory[j].TotalFreeBytes - memory[i].TotalFreeBytes < bytes) { j++; } } long actualCost = 0L; MemoryBlockByAddress resultBlock = this.structureByAddress[startIndex]; for (int i = startIndex + 1; i <= endIndex; i++) { MemoryBlockByAddress foundNode, block = this.structureByAddress[i]; long count = block.Address - resultBlock.End; this.memoryMove(resultBlock.End, resultBlock.Address, count); int sti = this.allocationsByAddress.GetLeftmostGreaterOrEqualIndex(new MemoryBlockByAddress(resultBlock.End, 0L), out foundNode); int eni = this.allocationsByAddress.GetLeftmostGreaterOrEqualIndex(new MemoryBlockByAddress(block.Address, 0L), out foundNode); actualCost += count; long delta = resultBlock.Size; for (int k = eni; --k >= sti;) { this.allocationsByAddress[k].Address -= delta; } resultBlock = new MemoryBlockByAddress(block.Address - resultBlock.Size, resultBlock.Size + block.Size); } if (actualCost != maxFreeBlockCost) { Debugger.Break(); } for (int i = endIndex + 1; --i >= startIndex;) { MemoryBlockBySize memoryBlockSize = this.structureByAddress[i].ToSize; this.structureBySize.Remove(memoryBlockSize); this.structureByAddress.RemoveAt(i); } this.structureByAddress.Add(resultBlock); this.structureBySize.Add(resultBlock.ToSize); }