using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace StabilityMatrix.Core.Helper.Cache; [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class LRUCache where TK : notnull { private readonly int capacity; private readonly Dictionary>> cacheMap = new(); private readonly LinkedList> lruList = new(); public LRUCache(int capacity) { this.capacity = capacity; } [MethodImpl(MethodImplOptions.Synchronized)] public TV? Get(TK key) { if (cacheMap.TryGetValue(key, out var node)) { var value = node.Value.Value; lruList.Remove(node); lruList.AddLast(node); return value; } return default; } public bool Get(TK key, out TV? value) { value = Get(key); return value != null; } [MethodImpl(MethodImplOptions.Synchronized)] public void Add(TK key, TV val) { if (cacheMap.TryGetValue(key, out var existingNode)) { lruList.Remove(existingNode); } else if (cacheMap.Count >= capacity) { RemoveFirst(); } var cacheItem = new LRUCacheItem(key, val); var node = new LinkedListNode>(cacheItem); lruList.AddLast(node); cacheMap[key] = node; } [MethodImpl(MethodImplOptions.Synchronized)] public void Remove(TK key) { if (!cacheMap.TryGetValue(key, out var node)) return; lruList.Remove(node); cacheMap.Remove(key); } private void RemoveFirst() { // Remove from LRUPriority var node = lruList.First; lruList.RemoveFirst(); if (node == null) return; // Remove from cache cacheMap.Remove(node.Value.Key); } } // ReSharper disable once InconsistentNaming internal class LRUCacheItem { public LRUCacheItem(TK k, TV v) { Key = k; Value = v; } public TK Key; public TV Value; }