/// <summary> /// Finds the first free memarea with enough required contigous space. /// </summary> /// <param name="memRequirements">space requirements</param> /// <returns>null if no such area exists, i.e view is full</returns> private MemArena FindFirstFreeArena(uint memRequirements) { memRequirements += (uint)MemArena.Header.Size; MemArena arena = FirstArena(); if (arena.OffsetNext != 0) { arena.Capacity = (uint)(arena.OffsetNext - (arena.Offset + MemArena.Header.Size)); } if (_lastFreeArena != null) //save time .This improves performance by many times.. I am saving the last free arena, to be used for next instert. This eliminates list traversal for every add operation. { if (_lastFreeArena.IsFree && _lastFreeArena.Capacity >= memRequirements) { return(_lastFreeArena); } } while (arena != null) { if (arena.IsFree && arena.Capacity >= memRequirements) { return(arena); } arena = arena.NextArena(); } return(null); }
bool IEnumerator.MoveNext() { if (_view == null) { return(false); } _storage._viewManager.OpenView(_view); if (_arena == null) { _arena = _view.FirstArena(); } else { _arena = _arena.NextArena(); if (_arena == null) { _view = _storage._viewManager.GetViewByID(_view.ID + 1); if (_view != null) { _storage._viewManager.OpenView(_view); _arena = _view.FirstArena(); } } } return(_arena != null); }
/// <summary> /// Splits an arena into two adjacent arenas. Size of the first arena is equal /// to the size parameter. The second arenas occupies rest of the size of the /// parent arena. /// </summary> internal static MemArena SplitArena(MemArena arena, uint size) { uint sizeWithHeader = (uint)(size + Header.Size); if (arena.OffsetNext != 0) //Quick and dirty... { arena.Capacity = (uint)(arena.OffsetNext - (arena.Offset + Header.Size)); } if (sizeWithHeader > arena.Capacity) //size is replaced by sizeWithHeader... { return(null); } uint remainingCapacity = (uint)(arena.Capacity - size - Header.Size); //if value is negative .uint gived garbage. Reason for above change. // Check if the remaining space will be useful at all! // if not then there is no need to split and use the whole // arena instead. if (remainingCapacity < MemArena.SPLIT_THRESHOLD) { arena.View.MyFreeSpace -= (uint)(arena.Capacity + Header.Size); return(arena); } // Reduce parent arena's capacity. arena.Capacity = size; MemArena newArena = arena.View.ArenaAtOffset(arena.Offset + arena.TotalLength); newArena.Capacity = remainingCapacity; arena.View.MyFreeSpace -= (sizeWithHeader); // Fix up links! MemArena tempArena = arena.NextArena(); SetNextArena(newArena, GetActualArena(tempArena)); SetNextArena(arena, newArena); return(newArena); }
public override string ToString() { StringBuilder b = new StringBuilder(); b.Append("View, ID=").Append(ID) .Append(", maxFree=").Append(MaxFreeSpace) .Append(", Free=").Append(FreeSpace) .Append("\r\n"); if (IsOpen) { MemArena next = FirstArena(); while (next != null) { b.Append(next.ToString()).Append("\r\n"); next = next.NextArena(); } } return(b.ToString()); }
/// <summary> /// /// </summary> /// <returns></returns> public MemArena DeFragment() { MemArena lastArena = FirstArena(); do { MemArena current = lastArena.NextArena(); if (current == null) { break; } // If the last arena is used we dont need to swap it down. if (!lastArena.IsFree) { lastArena = current; continue; } // Two consecutive free arenas, rare, but taken care of! if (current.IsFree) { lastArena = MemArena.CoalesceAdjacent(current); } else { // A free arena followed by a used one so we swap down the free one. MemArena.SwapAdjacent(current, lastArena); lastArena = current; } }while (true); this.FreeSpace = lastArena.Capacity; this.MaxFreeSpace = lastArena.Capacity; CalculateArenaMemoryUsage(); //may be we need it here.. very low frequency of this to be called.. return(lastArena); }
private void CalculateArenaMemoryUsage() { MemArena arena = FirstArena(); MemArena firstArena = FirstArena(); //need to keep the first ..for avoiding circular linkages.. uint maxFree = 0; uint totalFree = 0; while (arena != null) { try { if (arena.IsFree) { totalFree += arena.Capacity; if (arena.Capacity >= maxFree) { maxFree = arena.Capacity; } } arena = arena.NextArena(); if (arena != null) { if (arena.OffsetNext == firstArena.Offset) { arena.OffsetNext = 0; } } } catch (Exception e) { throw new Exception(e.Message); } } this.FreeSpace = totalFree; this.MaxFreeSpace = maxFree; this.MyFreeSpace = this.FreeSpace + (uint)MemArena.Header.Size; }
/// <summary> /// Coalesces/Merges all the adjacent FREE arenas into one arena. /// </summary> internal static MemArena CoalesceAdjacent(MemArena arena) { // Only free arenas can be coalesced. if (!arena.IsFree) { return(arena); } // Check if there is an arena next to this one. MemArena curr = arena; MemArena next = arena.NextArena(); int nHeaderCount = 0;//need to know how many headers are being freed while merging free arenas. if (next != null) { uint freedSpace = 0; // Find the first USED arena below this arena in the view. // Skip/Merge all the free arenas along the way. while (next != null && next.IsFree) { nHeaderCount++; freedSpace += next.TotalLength; curr = next; next = next.NextArena(); } // Fix up links! if (freedSpace > 0) { arena.Capacity += freedSpace; uint nCapacity = arena.Capacity; arena = SetNextArena(arena, GetActualArena(next)); //update only the actual arena arena.Capacity = nCapacity; } } if (arena.HasPrevious) { uint freedSpace = 0; // Find the first USED arena above this arena in the view. // Skip/Merge all the free arenas along the way. MemArena cur = arena; MemArena prev = null; do { prev = cur.PreviousArena(); if (prev == null || !prev.IsFree) { break; } freedSpace += prev.TotalLength; cur = prev; nHeaderCount++; }while (true); // Fix up links! For even if we find previous arena free.. The last from previous is now our Pivot.Its call to adjust its Next then. if (freedSpace > 0) { arena.Capacity += freedSpace; uint nCapacity = arena.Capacity; MemArena tempNext = arena.NextArena(); arena = SetNextArena(cur, GetActualArena(next)); //update only the actual arena arena.Capacity = nCapacity; } } if (nHeaderCount > 0) //update memory freed, while merging arenas. { arena.View.MyFreeSpace += (uint)(nHeaderCount * Header.Size); } return(arena); }