/// <summary> /// Remove old items or items beyond capacity from LifespanMgr allowing them to be garbage collected /// </summary> /// <remarks> /// Since we do not physically move items when touched we must check items in bag to determine if they should /// be deleted or moved. Also items that were removed by setting value to null get removed now. Rremoving /// an item from LifespanMgr allows it to be garbage collected. If removed item is retrieved by index prior /// to GC then it will be readded to LifespanMgr. /// </remarks> private void CleanUp(DateTime now) { lock (this) { int itemsAboveCapacity = Stats.Current - Stats.Capacity; AgeBag <T> bag = bags[OldestBagIndex]; while (AlmostOutOfBags || bag.HasExpired(maxAge, now) || (itemsAboveCapacity > 0 && bag.HasReachedMinimumAge(minAge, now))) { // cache is still too big / old so remove oldest bag Node <T> node = bag.First; bag.First = null; while (node != null) { Node <T> next = node.Next; node.Next = null; if (node.Value != null && node.Bag != null) { if (node.Bag == bag) { // item has not been touched since bag was closed, so remove it from LifespanMgr ++itemsAboveCapacity; node.Remove(); } else { // item has been touched and should be moved to correct age bag now node.Next = node.Bag.First; node.Bag.First = node; } } node = next; } bag = bags[++OldestBagIndex]; if (HasProcessedAllBags) { break; } } OpenBag(++CurrentBagIndex); EnsureIndexIsValid(); } }
private bool BagNeedsCleaning(AgeBag <T> bag, int itemsAboveCapacity, DateTime now) { return(bag.HasExpired(maxAge, now) || (itemsAboveCapacity > 0 && bag.HasReachedMinimumAge(minAge, now))); }