예제 #1
0
        /// <summary>
        /// Prune cache.
        /// </summary>
        void Prune(object _discard, System.Timers.ElapsedEventArgs _2)
        {
            if (disposed)
            {
                return;                       // dumbness with timers
            }
            if (!Atomic.Lock(ref prune_in_progress))
            {
                return;                                                  // only one instance.
            }
            try
            {
                if (Items.Count <= MinCache)
                {
                    return;                                          // just don't bother
                }
                if (Items.Count <= AbsoluteCapacity && CacheEvictStrategy == EvictStrategy.LeastUsed)
                {
                    return;
                }

                var list = Items.Values.ToList();                 // would be nice to cache this list

                list.Sort((CacheItem <TKey, TValue> x, CacheItem <TKey, TValue> y) =>
                {
                    if (CacheEvictStrategy == EvictStrategy.LeastRecent)
                    {
                        if (x.Access < y.Access)
                        {
                            return(-1);
                        }
                        if (x.Access > y.Access)
                        {
                            return(1);
                        }
                        // Both have equal at this point
                        if (x.Desirability < y.Desirability)
                        {
                            return(-1);
                        }
                        if (x.Desirability > y.Desirability)
                        {
                            return(1);
                        }
                    }
                    else                     // EvictStrategy.LeastUsed
                    {
                        if (x.Desirability < y.Desirability)
                        {
                            return(-1);
                        }
                        if (x.Desirability > y.Desirability)
                        {
                            return(1);
                        }
                        // Both have equal at this point
                        if (x.Access < y.Access)
                        {
                            return(-1);
                        }
                        if (x.Access > y.Access)
                        {
                            return(1);
                        }
                    }

                    return(0);
                });

                while (Items.Count > AbsoluteCapacity)
                {
                    var bu  = list[0];
                    var key = bu.AccessKey;
                    Items.TryRemove(key, out _);
                    list.Remove(bu);
                }

                var deleteItem = new Action <TKey>(
                    (TKey key) =>
                {
                    //Debug.WriteLine($"MKAh.SimpleCache removing {bi:N1} min old item.");
                    if (Items.TryRemove(key, out var item))
                    {
                        list.Remove(item);
                    }
                }
                    );

                var now = DateTimeOffset.UtcNow;
                while (list.Count > 0)
                {
                    var    bu = list[0];
                    double bi = now.Since(bu.Access).TotalMinutes;

                    if (CacheEvictStrategy == EvictStrategy.LeastRecent)
                    {
                        if (bi > MaxAge)
                        {
                            deleteItem(bu.AccessKey);
                        }
                        else
                        {
                            break;
                        }
                    }
                    else                     // .LeastUsed
                    {
                        if (bi > MinAge)
                        {
                            deleteItem(bu.AccessKey);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
            finally
            {
                Atomic.Unlock(ref prune_in_progress);
            }
        }