Guest User

Untitled

a guest
Jan 18th, 2019
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.87 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8.  
  9. namespace Caching
  10. {
  11. /// <summary>
  12. /// LRU cache that internally uses tuples. T1 is the type of the key, and T2 is the type of the value.
  13. /// </summary>
  14. public class LRUCache<T1, T2>
  15. {
  16. /// <summary>
  17. /// Enable or disable console debugging.
  18. /// </summary>
  19. public bool Debug;
  20.  
  21. private int _Capacity;
  22. private int _EvictCount;
  23. private readonly object _CacheLock = new object();
  24. private Dictionary<T1, DataNode<T2>> _Cache;
  25.  
  26. /// <summary>
  27. /// Initialize the cache.
  28. /// </summary>
  29. /// <param name="capacity">Maximum number of entries.</param>
  30. /// <param name="evictCount">Number to evict when capacity is reached.</param>
  31. /// <param name="debug">Enable or disable console debugging.</param>
  32. public LRUCache(int capacity, int evictCount, bool debug)
  33. {
  34. _Capacity = capacity;
  35. _EvictCount = evictCount;
  36. Debug = debug;
  37. _Cache = new Dictionary<T1, DataNode<T2>>();
  38. // _Cache = new List<Tuple<string, T, DateTime, DateTime>>();
  39.  
  40. if (_EvictCount > _Capacity)
  41. {
  42. throw new ArgumentException("Evict count must be less than or equal to capacity.");
  43. }
  44. }
  45.  
  46. /// <summary>
  47. /// Retrieve the current number of entries in the cache.
  48. /// </summary>
  49. /// <returns>An integer containing the number of entries.</returns>
  50. public int Count()
  51. {
  52. lock (_CacheLock)
  53. {
  54. return _Cache.Count;
  55. }
  56. }
  57.  
  58. /// <summary>
  59. /// Retrieve the key of the oldest entry in the cache.
  60. /// </summary>
  61. /// <returns>String containing the key.</returns>
  62. public T1 Oldest()
  63. {
  64. if (_Cache == null || _Cache.Count < 1) return default(T1);
  65.  
  66. lock (_CacheLock)
  67. {
  68. KeyValuePair<T1, DataNode<T2>> oldest = _Cache.Where(x => x.Value.Added != null).OrderBy(x => x.Value.Added).First();
  69. return oldest.Key;
  70. }
  71. }
  72.  
  73. /// <summary>
  74. /// Retrieve the key of the newest entry in the cache.
  75. /// </summary>
  76. /// <returns>String containing the key.</returns>
  77. public T1 Newest()
  78. {
  79. if (_Cache == null || _Cache.Count < 1) return default(T1);
  80.  
  81. lock (_CacheLock)
  82. {
  83. KeyValuePair<T1, DataNode<T2>> newest = _Cache.Where(x => x.Value.Added != null).OrderBy(x => x.Value.Added).Last();
  84. return newest.Key;
  85. }
  86. }
  87.  
  88. /// <summary>
  89. /// Retrieve the key of the last used entry in the cache.
  90. /// </summary>
  91. /// <returns>String containing the key.</returns>
  92. public T1 LastUsed()
  93. {
  94. if (_Cache == null || _Cache.Count < 1) return default(T1);
  95.  
  96. lock (_CacheLock)
  97. {
  98. KeyValuePair<T1, DataNode<T2>> lastUsed = _Cache.Where(x => x.Value.LastUsed != null).OrderBy(x => x.Value.LastUsed).Last();
  99. return lastUsed.Key;
  100. }
  101. }
  102.  
  103. /// <summary>
  104. /// Retrieve the key of the first used entry in the cache.
  105. /// </summary>
  106. /// <returns>String containing the key.</returns>
  107. public T1 FirstUsed()
  108. {
  109. if (_Cache == null || _Cache.Count < 1) return default(T1);
  110.  
  111. lock (_CacheLock)
  112. {
  113. KeyValuePair<T1, DataNode<T2>> firstUsed = _Cache.Where(x => x.Value.LastUsed != null).OrderBy(x => x.Value.LastUsed).First();
  114. return firstUsed.Key;
  115. }
  116. }
  117.  
  118. /// <summary>
  119. /// Clear the cache.
  120. /// </summary>
  121. public void Clear()
  122. {
  123. lock (_CacheLock)
  124. {
  125. _Cache = new Dictionary<T1, DataNode<T2>>();
  126. return;
  127. }
  128. }
  129.  
  130. /// <summary>
  131. /// Retrieve a key's value from the cache.
  132. /// </summary>
  133. /// <param name="key">The key associated with the data you wish to retrieve.</param>
  134. /// <returns>The object data associated with the key.</returns>
  135. public T2 Get(T1 key)
  136. {
  137. if (key == null) throw new ArgumentNullException(nameof(key));
  138.  
  139. lock (_CacheLock)
  140. {
  141. if (_Cache.ContainsKey(key))
  142. {
  143. KeyValuePair<T1, DataNode<T2>> curr = _Cache.Where(x => x.Key.Equals(key)).First();
  144.  
  145. // update LastUsed
  146. _Cache.Remove(key);
  147. curr.Value.LastUsed = DateTime.Now;
  148. _Cache.Add(key, curr.Value);
  149.  
  150. // return data
  151. return curr.Value.Data;
  152. }
  153. else
  154. {
  155. throw new KeyNotFoundException();
  156. }
  157. }
  158. }
  159.  
  160. /// <summary>
  161. /// Retrieve a key's value from the cache.
  162. /// </summary>
  163. /// <param name="key">The key associated with the data you wish to retrieve.</param>
  164. /// <param name="val">The value associated with the key.</param>
  165. /// <returns>True if key is found.</returns>
  166. public bool TryGet(T1 key, out T2 val)
  167. {
  168. if (key == null) throw new ArgumentNullException(nameof(key));
  169.  
  170. lock (_CacheLock)
  171. {
  172. if (_Cache.ContainsKey(key))
  173. {
  174. KeyValuePair<T1, DataNode<T2>> curr = _Cache.Where(x => x.Key.Equals(key)).First();
  175.  
  176. // update LastUsed
  177. _Cache.Remove(key);
  178. curr.Value.LastUsed = DateTime.Now;
  179. _Cache.Add(key, curr.Value);
  180.  
  181. // return data
  182. val = curr.Value.Data;
  183. return true;
  184. }
  185. else
  186. {
  187. val = default(T2);
  188. return false;
  189. }
  190. }
  191. }
  192.  
  193. /// <summary>
  194. /// Add or replace a key's value in the cache.
  195. /// </summary>
  196. /// <param name="key">The key.</param>
  197. /// <param name="val">The value associated with the key.</param>
  198. /// <returns>Boolean indicating success.</returns>
  199. public void AddReplace(T1 key, T2 val)
  200. {
  201. if (key == null) throw new ArgumentNullException(nameof(key));
  202.  
  203. lock (_CacheLock)
  204. {
  205. if (_Cache.ContainsKey(key))
  206. {
  207. _Cache.Remove(key);
  208. }
  209.  
  210. if (_Cache.Count >= _Capacity)
  211. {
  212. _Cache = _Cache.OrderBy(x => x.Value.LastUsed).Skip(_EvictCount).ToDictionary(x => x.Key, x => x.Value);
  213. }
  214.  
  215. DataNode<T2> curr = new DataNode<T2>(val);
  216. _Cache.Add(key, curr);
  217. return;
  218. }
  219. }
  220.  
  221. /// <summary>
  222. /// Remove a key from the cache.
  223. /// </summary>
  224. /// <param name="key">The key.</param>
  225. public void Remove(T1 key)
  226. {
  227. if (key == null) throw new ArgumentNullException(nameof(key));
  228.  
  229. lock (_CacheLock)
  230. {
  231. if (_Cache.ContainsKey(key))
  232. {
  233. _Cache.Remove(key);
  234. }
  235.  
  236. return;
  237. }
  238. }
  239.  
  240. /// <summary>
  241. /// Retrieve all keys in the cache.
  242. /// </summary>
  243. /// <returns>List of string.</returns>
  244. public List<T1> GetKeys()
  245. {
  246. lock (_CacheLock)
  247. {
  248. List<T1> keys = new List<T1>(_Cache.Keys);
  249. return keys;
  250. }
  251. }
  252. }
  253. }
Add Comment
Please, Sign In to add comment