LRUCache.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. using System.Collections.Generic;
  2. namespace CommonAIClient.Unity.Utils
  3. {
  4. public class LRUCache<K, V>
  5. {
  6. public delegate void BeforRemoveDelegate(V val);
  7. private BeforRemoveDelegate OnBeforRemove = null;
  8. public LRUCache(int capacity, BeforRemoveDelegate function)
  9. {
  10. this.capacity = capacity;
  11. this.OnBeforRemove = function;
  12. }
  13. public V Get(K key)
  14. {
  15. HashSet<LinkedListNode<LRUCacheItem<K, V>>> nodes;
  16. if (cacheMap.TryGetValue(key, out nodes))
  17. {
  18. //System.Console.WriteLine("Cache HIT " + key);
  19. var iter = nodes.GetEnumerator();
  20. iter.MoveNext();
  21. LinkedListNode<LRUCacheItem<K, V>> node = iter.Current;
  22. V value = node.Value.value;
  23. nodes.Remove(node);
  24. lruList.Remove(node);
  25. //lruList.AddLast(node);
  26. return value;
  27. }
  28. //System.Console.WriteLine("Cache MISS " + key);
  29. return default(V);
  30. }
  31. public void Add(K key, V val)
  32. {
  33. if (capacity > 0)
  34. {
  35. if (lruList.Count >= capacity)
  36. {
  37. removeFirst();
  38. }
  39. LRUCacheItem<K, V> cacheItem = new LRUCacheItem<K, V>(key, val);
  40. LinkedListNode<LRUCacheItem<K, V>> node = new LinkedListNode<LRUCacheItem<K, V>>(cacheItem);
  41. lruList.AddLast(node);
  42. if (!cacheMap.ContainsKey(key))
  43. cacheMap.Add(key, new HashSet<LinkedListNode<LRUCacheItem<K, V>>>());
  44. cacheMap[key].Add(node);
  45. }
  46. else
  47. {
  48. if (this.OnBeforRemove != null) this.OnBeforRemove(val);
  49. }
  50. }
  51. public bool ContainsKey(K key)
  52. {
  53. if (!cacheMap.ContainsKey(key))
  54. return false;
  55. else
  56. {
  57. if (cacheMap[key].Count == 0)
  58. {
  59. return false;
  60. }
  61. else
  62. {
  63. var iter = cacheMap[key].GetEnumerator();
  64. iter.MoveNext();
  65. LinkedListNode<LRUCacheItem<K, V>> node = iter.Current;
  66. V value = node.Value.value;
  67. if (value == null || (value is UnityEngine.Object && (value as UnityEngine.Object) == null))
  68. {
  69. //GameDebug.Log("what fuck? " + key.ToString());
  70. lruList.Remove(node);
  71. cacheMap[key].Remove(node);
  72. return false;
  73. }
  74. else
  75. {
  76. return true;
  77. }
  78. }
  79. }
  80. }
  81. public void Clear()
  82. {
  83. while (cacheMap.Count > 0 && lruList.First != null)
  84. {
  85. removeFirst();
  86. }
  87. }
  88. protected void removeFirst()
  89. {
  90. // Remove from LRUPriority
  91. LinkedListNode<LRUCacheItem<K, V>> node = lruList.First;
  92. if (node != null)
  93. {
  94. if (this.OnBeforRemove != null) this.OnBeforRemove(node.Value.value);
  95. lruList.RemoveFirst();
  96. // Remove from cache
  97. //cacheMap.Remove(node.Value.key);
  98. cacheMap[node.Value.key].Remove(node);
  99. }
  100. }
  101. int capacity;
  102. Dictionary<K, HashSet<LinkedListNode<LRUCacheItem<K, V>>>> cacheMap =
  103. new Dictionary<K, HashSet<LinkedListNode<LRUCacheItem<K, V>>>>();
  104. LinkedList<LRUCacheItem<K, V>> lruList = new LinkedList<LRUCacheItem<K, V>>();
  105. }
  106. internal class LRUCacheItem<K, V>
  107. {
  108. public LRUCacheItem(K k, V v)
  109. {
  110. key = k;
  111. value = v;
  112. }
  113. public K key;
  114. public V value;
  115. }
  116. }