using System.Collections.Generic; namespace CommonAIClient.Unity.Utils { public class LRUCache { public delegate void BeforRemoveDelegate(V val); private BeforRemoveDelegate OnBeforRemove = null; public LRUCache(int capacity, BeforRemoveDelegate function) { this.capacity = capacity; this.OnBeforRemove = function; } public V Get(K key) { HashSet>> nodes; if (cacheMap.TryGetValue(key, out nodes)) { //System.Console.WriteLine("Cache HIT " + key); var iter = nodes.GetEnumerator(); iter.MoveNext(); LinkedListNode> node = iter.Current; V value = node.Value.value; nodes.Remove(node); lruList.Remove(node); //lruList.AddLast(node); return value; } //System.Console.WriteLine("Cache MISS " + key); return default(V); } public void Add(K key, V val) { if (capacity > 0) { if (lruList.Count >= capacity) { removeFirst(); } LRUCacheItem cacheItem = new LRUCacheItem(key, val); LinkedListNode> node = new LinkedListNode>(cacheItem); lruList.AddLast(node); if (!cacheMap.ContainsKey(key)) cacheMap.Add(key, new HashSet>>()); cacheMap[key].Add(node); } else { if (this.OnBeforRemove != null) this.OnBeforRemove(val); } } public bool ContainsKey(K key) { if (!cacheMap.ContainsKey(key)) return false; else { if (cacheMap[key].Count == 0) { return false; } else { var iter = cacheMap[key].GetEnumerator(); iter.MoveNext(); LinkedListNode> node = iter.Current; V value = node.Value.value; if (value == null || (value is UnityEngine.Object && (value as UnityEngine.Object) == null)) { //GameDebug.Log("what fuck? " + key.ToString()); lruList.Remove(node); cacheMap[key].Remove(node); return false; } else { return true; } } } } public void Clear() { while (cacheMap.Count > 0 && lruList.First != null) { removeFirst(); } } protected void removeFirst() { // Remove from LRUPriority LinkedListNode> node = lruList.First; if (node != null) { if (this.OnBeforRemove != null) this.OnBeforRemove(node.Value.value); lruList.RemoveFirst(); // Remove from cache //cacheMap.Remove(node.Value.key); cacheMap[node.Value.key].Remove(node); } } int capacity; Dictionary>>> cacheMap = new Dictionary>>>(); LinkedList> lruList = new LinkedList>(); } internal class LRUCacheItem { public LRUCacheItem(K k, V v) { key = k; value = v; } public K key; public V value; } }