/// <summary> /// Allocates a section with the given size from the normal free sections. /// </summary> /// <param name="size">The size of the section to allocate.</param> /// <returns>The allocated section.</returns> private HeapSection AllocateSection(int size) { HeapSection currFreeSect = this.freeSectionsHead; while (currFreeSect.Length != -1 && currFreeSect.Length < size && currFreeSect != null) { currFreeSect = currFreeSect.Next; } if (currFreeSect == null) { throw new HeapException("Heap is full!"); } if (currFreeSect.Length == size) { /// Size exactly fits, allocate the section if (currFreeSect.Next != null && currFreeSect.Prev != null) { /// Non-head currFreeSect.Prev.Next = currFreeSect.Next; currFreeSect.Next.Prev = currFreeSect.Prev; currFreeSect.Next = null; currFreeSect.Prev = null; } else if (currFreeSect.Prev == null && currFreeSect.Next != null) { /// Head this.freeSectionsHead = currFreeSect.Next; currFreeSect.Next.Prev = null; currFreeSect.Next = null; } else { throw new HeapException("Unexpected case!"); } return(currFreeSect); } else { /// Size doesn't fit exactly, need to split the section. HeapSection newSection = this.sectionObjectPool.Count != 0 ? this.sectionObjectPool.Dequeue() : new HeapSection(); newSection.Address = currFreeSect.Address; newSection.Length = size; newSection.Next = null; newSection.Prev = null; currFreeSect.Address = newSection.Address + newSection.Length; if (currFreeSect.Length != -1) { currFreeSect.Length -= size; } return(newSection); } }
/// <see cref="IHeapManagerInternals.New"/> public IHeapConnector New(short typeID) { if (this.heap == null) { throw new InvalidOperationException("No simulation heap created or loaded currently!"); } if (typeID < 0 || typeID >= this.types.Count) { throw new ArgumentOutOfRangeException("typeID"); } HeapType type = this.types[typeID]; HeapSection sectToAlloc = this.AllocateSection(type.AllocationSize); return(this.CreateHeapConnector(sectToAlloc.Address, typeID)); }
/// <see cref="IHeapManagerInternals.NewArray"/> public IHeapConnector NewArray(short typeID, int count) { if (this.heap == null) { throw new InvalidOperationException("No simulation heap created or loaded currently!"); } if (typeID < 0 || typeID >= this.types.Count) { throw new ArgumentOutOfRangeException("typeID"); } if (count <= 0) { throw new ArgumentOutOfRangeException("count"); } HeapType type = this.types[typeID]; HeapSection sectToAlloc = this.AllocateSection(count * type.AllocationSize + 4); /// +4 is for storing the number of array-items. this.heap.WriteInt(sectToAlloc.Address, count); return(this.CreateHeapConnector(sectToAlloc.Address + 4, typeID)); }
/// <summary> /// Deallocates the given simulation heap section. /// </summary> /// <param name="address">The start address of the section to be deallocated.</param> /// <param name="length">The length of the section to be deallocated.</param> private void DeallocateSection(int address, int length) { HeapSection section = this.sectionObjectPool.Count != 0 ? this.sectionObjectPool.Dequeue() : new HeapSection(); section.Address = address; section.Length = length; section.Next = null; section.Prev = null; HeapSection currFreeSect = this.freeSectionsHead; while (section.Address > currFreeSect.Address) { currFreeSect = currFreeSect.Next; } if (section.Address + section.Length < currFreeSect.Address) { /// Insert the deallocated section before currFreeSect. section.Next = currFreeSect; section.Prev = currFreeSect.Prev; currFreeSect.Prev = section; if (section.Prev != null) { section.Prev.Next = section; } else { this.freeSectionsHead = section; } } else if (section.Address + section.Length == currFreeSect.Address) { /// Merge the deallocated section with currFreeSect. currFreeSect.Address -= section.Length; if (currFreeSect.Length != -1) { currFreeSect.Length += section.Length; } this.sectionObjectPool.Enqueue(section); section = currFreeSect; } else { throw new HeapException("Unexpected case!"); } if (section.Prev != null) { if (section.Prev.Address + section.Prev.Length == section.Address) { /// Merge the section with section.Prev. HeapSection sectToDel = section.Prev; section.Address -= section.Prev.Length; if (section.Length != -1) { section.Length += section.Prev.Length; } section.Prev = section.Prev.Prev; this.sectionObjectPool.Enqueue(sectToDel); if (section.Prev != null) { section.Prev.Next = section; } else { this.freeSectionsHead = section; } } else if (section.Prev.Address + section.Prev.Length > section.Address) { throw new HeapException("Unexpected case!"); } } }