/// <summary> /// Resize the heap encreasing the size by the specified value mantaining all data /// in the same position. /// </summary> /// <param name="size">Grow size in bytes (the actual grow size could be bigger than the specified).</param> /// <param name="noOvergrowth">Force the allocator to grow the heap by the exact specified size.</param> /// <returns>Returns <see cref="true"/> if the memory allocation has been done.</returns> public virtual bool Grow(uint size, bool noOvergrowth = false) { // - Check if the heap can grow if (!CanGrow) { return(false); } // - Check if we reached the memory limit if (HeapSize + size > MaximumSize) { return(false); } // - Calculates the actual grow size uint growSize = noOvergrowth ? size : (uint)(size + GrowFactor * HeapSize); try { // - Realloc the heap memory RawMemory = Marshal.ReAllocHGlobal(RawMemory, new IntPtr(HeapSize + growSize)); } catch (OutOfMemoryException) { return(false); } // - Gets the last avaiable chunk of memory var lastChunk = FreeSpace.LastOrDefault(); // - Create a new memory pointer pointing to the last block if there's no free block at the end if (lastChunk == null || lastChunk.Offset + lastChunk.Size < HeapSize) { FreeSpace.Add(new MemoryPointer(this, growSize, HeapSize)); } // - Modify the existing chunk if it's at the end of the heap if (lastChunk != null || lastChunk.Offset + lastChunk.Size >= HeapSize) { lastChunk.ChangeOffsetAndSize(lastChunk.Offset, lastChunk.Size + growSize); } // - Update the heap size HeapSize += growSize; return(true); }
/// <summary> /// Shrinks the heap memory to the smallest memory that contains /// all the allocated blocks. /// </summary> /// <param name="keepBytes">Number of bytes to keep at the heap's tail.</param> /// <returns>Returns <see cref="true"/> if the shring goes well.</returns> public virtual bool FreeUnusedMemory(int keepBytes = -1) { // - Gets the last avaiable chunk of memory var lastChunk = FreeSpace.LastOrDefault(); // - Create a new memory pointer pointing to the last block if there's no free block at the end if (lastChunk != null || lastChunk.Offset + lastChunk.Size >= HeapSize) { // - Automatically takes 10% of the whole size free if keepBytes is -1 if (keepBytes < 0) { keepBytes = (int)System.Math.Ceiling(HeapSize * 0.1); } // - Calculate the amount of memory to free uint shrinkSize = (uint)System.Math.Max(lastChunk.Size - keepBytes, 0); if (shrinkSize > 0) { try { // - Realloc the heap memory RawMemory = Marshal.ReAllocHGlobal(RawMemory, new IntPtr(HeapSize - shrinkSize)); // - Resize the last chunk if (lastChunk.Size - shrinkSize > 0) { lastChunk.ChangeOffsetAndSize(lastChunk.Offset, lastChunk.Size - shrinkSize); } else { FreeSpace.Remove(lastChunk); } HeapSize -= shrinkSize; } catch (OutOfMemoryException) { return(false); } } } return(true); }