public MemoryBlockByAddress Allocate(long bytes) { if (bytes <= 0L) { return(new MemoryBlockByAddress(0L, 0L)); } MemoryBlockBySize existing, sizeRequest = new MemoryBlockBySize(0L, bytes); this.structureBySize.GetLeftmostGreaterOrEqualIndex(sizeRequest, out existing); while (existing.Size < bytes) { this.assureFreeMemory(bytes); this.structureBySize.GetLeftmostGreaterOrEqualIndex(sizeRequest, out existing); } MemoryBlockByAddress result = new MemoryBlockByAddress(existing.Address, bytes); MemoryBlockBySize replacer = new MemoryBlockBySize(existing.Address + bytes, existing.Size - bytes); this.structureBySize.Remove(existing); this.structureByAddress.Remove(existing.ToAddress); if (replacer.Size > 0L) { this.structureBySize.Add(replacer); this.structureByAddress.Add(replacer.ToAddress); } this.free -= bytes; //this.memFill(result.Address, result.Size, (byte)result.Size); this.allocationsByAddress.Add(result); return(result); }
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); }
public void Free(MemoryBlockByAddress memoryBlock) { if (memoryBlock.Size <= 0L) { return; } //if (!memCheck(memoryBlock.Address, memoryBlock.Size, (byte)memoryBlock.Size)) //{ // Debugger.Break(); //} bool ok = this.allocationsByAddress.Remove(memoryBlock); if (!ok) { throw new InvalidOperationException("Free called to not allocated memory pointer."); } MemoryBlockByAddress existing; int index = this.structureByAddress.GetLeftmostGreaterOrEqualIndex(memoryBlock, out existing); MemoryBlockByAddress previous = index <= 0 ? new MemoryBlockByAddress(-1L, 0L) : this.structureByAddress[index - 1]; long overlap = memoryBlock.GetOverlap(previous); if (previous.End == memoryBlock.Address) { memoryBlock = new MemoryBlockByAddress(previous.Address, previous.Size + memoryBlock.Size); this.structureByAddress.Remove(previous); this.structureBySize.Remove(previous.ToSize); this.free -= previous.Size; } if (existing != null) { overlap = Math.Max(overlap, memoryBlock.GetOverlap(existing)); if (memoryBlock.End == existing.Address) { memoryBlock = new MemoryBlockByAddress(memoryBlock.Address, memoryBlock.Size + existing.Size); this.structureByAddress.Remove(existing); this.structureBySize.Remove(existing.ToSize); this.free -= existing.Size; } } this.structureBySize.Add(memoryBlock.ToSize); this.structureByAddress.Add(memoryBlock); this.free += memoryBlock.Size; if (overlap > 0) { Debugger.Break(); throw new InvalidOperationException("Overlap between dispose and already free memory."); } }
public long GetOverlap(MemoryBlockByAddress address) { return(Math.Min(this.End, address.End) - Math.Max(this.Address, address.Address)); }
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); }