Beispiel #1
0
 /// <summary>Create item enumerator</summary>
 public IEnumerator <Node> GetEnumerator()
 {
     lock (this)
     {
         for (int bagNumber = _current; bagNumber >= _oldest; --bagNumber)
         {
             AgeBag bag = _bags[bagNumber];
             // if bag.first == null then bag is empty or being cleaned up, so skip it!
             for (Node node = bag.First; node != null && bag.First != null; node = node.Next)
             {
                 if (node.Value != null)
                 {
                     yield return(node);
                 }
             }
         }
     }
 }
Beispiel #2
0
 /// <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>
 public void CleanUp(DateTime now)
 {
     lock (this) {
         //calculate how many items should be removed
         DateTime maxAge        = now.Subtract(_maxAge);
         DateTime minAge        = now.Subtract(_minAge);
         int      itemsToRemove = _owner._curCount - _owner._capacity;
         AgeBag   bag           = _bags[_oldest % _size];
         while (_current != _oldest &&
                (_current - _oldest > _size - 5 || bag.startTime < maxAge ||
                 (itemsToRemove > 0 && bag.stopTime > minAge)))
         {
             // cache is still too big / old so remove oldest bag
             Node node = bag.first;
             bag.first = null;
             while (node != null)
             {
                 Node next = node.next;
                 node.next = null;
                 if (node.Value != null && node.ageBag != null)
                 {
                     if (node.ageBag == bag)
                     {
                         // item has not been touched since bag was closed, so remove it from LifespanMgr
                         ++itemsToRemove;
                         node.ageBag = null;
                         Interlocked.Decrement(ref _owner._curCount);
                     }
                     else
                     {
                         // item has been touched and should be moved to correct age bag now
                         node.next         = node.ageBag.first;
                         node.ageBag.first = node;
                     }
                 }
                 node = next;
             }
             // increment oldest bag
             bag = _bags[(++_oldest) % _size];
         }
         OpenCurrentBag(now, ++_current);
         CheckIndexValid();
     }
 }
Beispiel #3
0
 /// <summary>ready a new current AgeBag for use and close the previous one</summary>
 private void OpenCurrentBag(DateTime now, int bagNumber)
 {
     lock (this)
     {
         // close last age bag
         if (_currentBag != null)
         {
             _currentBag.stopTime = now;
         }
         // open new age bag for next time slice
         AgeBag currentBag = _bags[(_current = bagNumber) % _size];
         currentBag.startTime = now;
         currentBag.first     = null;
         _currentBag          = currentBag;
         // reset counters for CheckValid()
         _nextValidCheck = now.Add(_timeSlice);
         _currentSize    = 0;
     }
 }
Beispiel #4
0
 /// <summary>Updates the status of the node to prevent it from being dropped from cache</summary>
 public void Touch()
 {
     if (Value != null && ageBag != _mgr._currentBag)
     {
         if (ageBag == null)
         {
             lock (_mgr)
                 if (ageBag == null)
                 {
                     // if node.AgeBag==null then the object is not currently managed by LifespanMgr so add it
                     next = _mgr._currentBag.first;
                     _mgr._currentBag.first = this;
                     Interlocked.Increment(ref _mgr._owner._curCount);
                 }
         }
         ageBag = _mgr._currentBag;
         Interlocked.Increment(ref _mgr._currentSize);
     }
     _mgr.CheckValid();
 }