private void MoveToHead(LRUCacheNode node) { _head.prev = node; node.next = _head; node.prev = null; _head = node; }
public bool TryGetValue(K key, out V val) { _counters.CacheReadPerSec.Increment(); LRUCacheNode node = null; lock (_syncRoot) { if (_data.TryGetValue(key, out node)) { _order.Remove(node.TimeKey); node.TimeKey = Stopwatch.GetTimestamp(); AddOrder(node.TimeKey, key); } } if (node == null) { _counters.CacheHitRatio.IncreaseFraction(false); val = default(V); return(false); } else { _counters.CacheHitRatio.IncreaseFraction(true); val = node.Value; return(true); } }
private void Evict() { _keyToNodeDictionary.Remove(_tail.key); _tail = _tail?.prev; if (_tail?.next != null) { _tail.next = null; } }
/// <summary> /// Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item. /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void Insert(string key, int value) { LRUCacheNode newEntry; if (_keyToNodeDictionary.ContainsKey(key)) { _keyToNodeDictionary[key].val = value; newEntry = _keyToNodeDictionary[key]; // Update MRU and LRU in case they point to this node if (newEntry == _tail) { _tail = _tail.prev; } else if (newEntry == _head) { _head = _head.next; } // Detach from DLL newEntry.Detach(); } else { newEntry = new LRUCacheNode(key, value); // Eviction based on LRU if (_currentSize == _maxSize) { Evict(); } else { _currentSize++; // Only increment if it is not contained and currentSize < maxsize } _keyToNodeDictionary.Add(newEntry.key, newEntry); } // Update MRU var prevHead = _head; _head = newEntry; _head.next = prevHead; if (prevHead != null) { prevHead.prev = _head; } if (_tail == null) { _tail = newEntry; } }
public void Put(int key, int value) { if (_map.ContainsKey(key)) { var node = _map[key]; node.val = value; if (_head == node) { return; } else if (node == _tail) { RemoveTail(); } else { RemoveNode(node); } MoveToHead(node); } else { var node = new LRUCacheNode(key, value); _map.Add(key, node); if (_count == _capacity) // evicts { MoveToHead(node); _map.Remove(_tail.key); RemoveTail(); } else { if (_head == null) // count 0 { _head = _tail = node; } else if (_head == _tail) // count 1 { _tail.prev = node; node.next = _tail; _head = node; } else { MoveToHead(node); } _count++; } } }
/// <summary> /// Helper function to detach a node from the DLL List /// </summary> public void Detach() { if (prev != null) { prev.next = next; } if (next != null) { next.prev = prev; } prev = null; next = null; }
private void RemoveNode(LRUCacheNode node) { var prev = node.prev; var next = node.next; if (prev != null) { prev.next = next; } if (next != null) { next.prev = prev; } }
private void RemoveTail() { _tail = _tail.prev; _tail.next = null; }