/// <summary>
                /// Trims the LRU cache if needed.
                /// </summary>
                private void Trim()
                {
                    //
                    // NB: We can have temporary oversubscription during concurrent accesses because we avoid to enter the write lock
                    //     until absolutely necessary, so _cache.Count can be a dirty read.
                    //
                    if (_count >= _maxCapacity)
                    {
                        _lock.EnterWriteLock();
                        try
                        {
                            do
                            {
                                var entry = _lruList.Last;

                                if (entry.Key.TryGetTarget(out T key))
                                {
                                    _cache.Remove(key);
                                }

                                LruLinkedList.RemoveLast(ref _lruList);
                                Interlocked.Decrement(ref _count);
#if DEBUG
                                _lastEvicted = entry;
                                _evictionCount++;
#endif
                            } while (_count >= _maxCapacity);
                        }
                        finally
                        {
                            _lock.ExitWriteLock();
                        }
                    }
                }
Beispiel #2
0
                private void Trim()
                {
                    //
                    // NB: We can have temporary oversubscription during concurrent accesses because we avoid to enter the write lock
                    //     until absolutely necessary, so _entries.Count can be a dirty read.
                    //
                    if (_entries.Count >= _maxCapacity)
                    {
#if DEBUG
                        var trimStart = _stopwatch.ElapsedTicks;
#endif
                        _lock.EnterWriteLock();
                        try
                        {
                            using (var evictionOrder = _ranker.GetEnumerator())
                            {
                                while (_entries.Count >= _maxCapacity && evictionOrder.MoveNext())
                                {
                                    var entry = evictionOrder.Current;
#if DEBUG
                                    _lastEvicted = entry;
#endif
                                    if (entry.Key.TryGetTarget(out T key))
                                    {
                                        _cache.Remove(key);
                                    }

                                    _entries.Remove(entry);
#if DEBUG
                                    _evictionCount++;
#endif
                                }
                            }

                            _entries.RemoveWhere(e => !e.Key.TryGetTarget(out _));
                        }
                        finally
                        {
                            _lock.ExitWriteLock();
                        }
#if DEBUG
                        var trimElapsed = new TimeSpan(_stopwatch.ElapsedTicks - trimStart);
                        _trimCount++;
                        _trimElapsed += trimElapsed;
#endif
                    }
                }