private void MakeMostRecentlyUsed(MostRecentlyUsedCacheNode node) { if (node == _head) { return; } RemoveFromLinkedList(node); AddToHead(node); }
/// <summary> /// Removes all items from the cache. /// </summary> public void Clear() { using (_entriesSync.WriteLock()) { _nodesByKey.Clear(); _head = null; _tail = null; _currentCount = 0; } }
private void AddToHead(MostRecentlyUsedCacheNode node) { node.Previous = null; node.Next = _head; if (_head != null) { _head.Previous = node; } _head = node; }
/// <summary> /// Inserts a specified key and value into the cache. /// </summary> /// <param name="key">The key to add.</param> /// <param name="value">The value to add.</param> /// <exception cref="ArgumentNullException"><paramref name="key"/> was null.</exception> /// <remarks> /// Internall this method will : /// 1) If the cache is full, remove the MRU item from the cache. /// 2) If the specified key already exists in the cache, update the value held in the cache. /// 3) Mark the key/value added as the new MRU item in the cache. /// </remarks> public void Insert(TKey key, TValue value) { if (key == null) { throw new ArgumentNullException(nameof(key), $"Unable to insert into MRU Cache. {nameof(key)} parameter cannot be null"); } using (_entriesSync.WriteLock()) { MostRecentlyUsedCacheNode node; if (!_nodesByKey.TryGetValue(key, out node)) { //not in cache so insert //check another thread has not inserted the node if (!_nodesByKey.TryGetValue(key, out node)) { if (IsFull) { node = _head; _nodesByKey.Remove(_head.Key); node.Key = key; node.Value = value; } else { _currentCount++; node = new MostRecentlyUsedCacheNode { Key = key, Value = value }; } _nodesByKey.Add(key, node); } } else { //exists in cache so locak the node and update its' value lock (node) { node.Value = value; } } MakeMostRecentlyUsed(node); if (_tail == null) { _tail = _head; } } }
private void RemoveFromLinkedList(MostRecentlyUsedCacheNode node) { var nextNode = node.Next; var prevNode = node.Previous; if (nextNode != null) { nextNode.Previous = node.Previous; } if (prevNode != null) { prevNode.Next = node.Next; } if (_head == node) { _head = nextNode; } if (_tail == node) { _tail = prevNode; } }