Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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.");
            }
        }
Exemplo n.º 4
0
 public long GetOverlap(MemoryBlockByAddress address)
 {
     return(Math.Min(this.End, address.End) - Math.Max(this.Address, address.Address));
 }
Exemplo n.º 5
0
        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);
        }