Пример #1
0
        /// <summary>
        /// Deallocates a previously allocated block.
        /// </summary>
        /// <param name="address">The address of the block to deallocate.</param>
        public void Free(uint address)
        {
            HeapEntry entry = new HeapEntry(address, 0);
            int       index = blocks.BinarySearch(entry, entryComparer);

            if (index >= 0)
            {
                // delete the block
                entry = blocks[index];
                blocks.RemoveAt(index);

                // adjust the heap extent if necessary
                if (entry.Start + entry.Length - heapAddress == heapExtent)
                {
                    if (index == 0)
                    {
                        heapExtent = 0;
                    }
                    else
                    {
                        HeapEntry prev = blocks[index - 1];
                        heapExtent = prev.Start + prev.Length - heapAddress;
                    }
                }

                // add the block to the free list
                index = ~freeList.BinarySearch(entry, entryComparer);
                System.Diagnostics.Debug.Assert(index >= 0);
                freeList.Insert(index, entry);

                if (index < freeList.Count - 1)
                {
                    Coalesce(index, index + 1);
                }
                if (index > 0)
                {
                    Coalesce(index - 1, index);
                }

                // shrink the heap if necessary
                if (blocks.Count > 0 && heapExtent <= (endMem - heapAddress) / 2)
                {
                    if (setEndMem(heapAddress + heapExtent))
                    {
                        endMem = heapAddress + heapExtent;

                        for (int i = freeList.Count - 1; i >= 0; i--)
                        {
                            if (freeList[i].Start >= endMem)
                            {
                                freeList.RemoveAt(i);
                            }
                        }
                    }
                }
            }
        }
Пример #2
0
        private void Coalesce(int index1, int index2)
        {
            HeapEntry first  = freeList[index1];
            HeapEntry second = freeList[index2];

            if (first.Start + first.Length >= second.Start)
            {
                first.Length     = second.Start + second.Length - first.Start;
                freeList[index1] = first;
                freeList.RemoveAt(index2);
            }
        }
Пример #3
0
        /// <summary>
        /// Allocates a new block on the heap.
        /// </summary>
        /// <param name="size">The size of the new block, in bytes.</param>
        /// <returns>The address of the new block, or 0 if allocation failed.</returns>
        public uint Alloc(uint size)
        {
            HeapEntry result = new HeapEntry(0, size);

            // look for a free block
            if (freeList != null)
            {
                for (int i = 0; i < freeList.Count; i++)
                {
                    HeapEntry entry = freeList[i];
                    if (entry.Length >= size)
                    {
                        result.Start = entry.Start;

                        if (entry.Length > size)
                        {
                            // shrink the free block
                            entry.Start  += size;
                            entry.Length -= size;
                            freeList[i]   = entry;
                        }
                        else
                        {
                            freeList.RemoveAt(i);
                        }

                        break;
                    }
                }
            }

            if (result.Start == 0)
            {
                // enforce maximum heap size
                if (maxHeapExtent != 0 && heapExtent + size > maxHeapExtent)
                {
                    return(0);
                }

                // add a new block at the end
                result = new HeapEntry(heapAddress + heapExtent, size);

                if (heapAddress + heapExtent + size > endMem)
                {
                    // grow the heap
                    uint newHeapAllocation = Math.Max(
                        heapExtent * 5 / 4,
                        heapExtent + size);

                    if (maxHeapExtent != 0)
                    {
                        newHeapAllocation = Math.Min(newHeapAllocation, maxHeapExtent);
                    }

                    if (setEndMem(heapAddress + newHeapAllocation))
                    {
                        endMem = heapAddress + newHeapAllocation;
                    }
                    else
                    {
                        return(0);
                    }
                }

                heapExtent += size;
            }

            // add the new block to the list
            int index = ~blocks.BinarySearch(result, entryComparer);

            System.Diagnostics.Debug.Assert(index >= 0);
            blocks.Insert(index, result);

            return(result.Start);
        }