/// <summary> /// 将指定的节点添加到链表热端的头部。 /// </summary> /// <param name="node">要添加的节点。</param> private void AddHotFirst(LruNodeNoSync <TKey, TValue> node) { if (this.head == null) { node.Next = node.Prev = node; } else { this.head.AddBefore(node); // 热端长度增加,将冷端头节点像前移动一个位置。 if (this.codeHead != null) { this.codeHead = this.codeHead.Prev; } } this.head = node; }
/// <summary> /// 从链表中移除指定的节点。 /// </summary> /// <param name="node">要移除的节点。</param> private void Remove(LruNodeNoSync <TKey, TValue> node) { if (node.Next == node) { this.head = null; } else { node.Next.Prev = node.Prev; node.Prev.Next = node.Next; if (this.head == node) { this.head = node.Next; } else if (this.codeHead == node) { this.codeHead = node.Next; } } }
/// <summary> /// 将指定的键和对象添加到缓存中,并返回添加的节点。 /// </summary> /// <param name="key">要添加的对象的键。</param> /// <param name="value">要添加的对象。</param> private void AddInternal(TKey key, TValue value) { LruNodeNoSync <TKey, TValue> node; if (count < maxSize) { // 将节点添加到热端的头。 node = new LruNodeNoSync <TKey, TValue>(key, value); AddHotFirst(node); count++; if (count == hotSize + 1) { codeHead = head.Prev; } } else { // 从冷端末尾尝试淘汰旧节点,将访问次数大于 1 的移动到热端的头。 // 由于双向链表是环形存储的,就相当于将 head 前移。 while (head.Prev.VisitCount >= 2) { // 清零访问计数。 head.Prev.VisitCount = 0; head = head.Prev; codeHead = codeHead.Prev; } // 将 node 移除,并添加到冷端的头。 node = head.Prev; this.cacheDict.Remove(node.Key); this.Remove(node); // 这里直接重用旧节点。 node.Key = key; node.Value = value; node.VisitCount = 1; this.AddCodeFirst(node); } cacheDict.Add(key, node); }
/// <summary> /// 将指定的节点添加到链表冷端的头部。 /// </summary> /// <param name="node">要添加的节点。</param> private void AddCodeFirst(LruNodeNoSync <TKey, TValue> node) { // 这里 codeHead != null,在调用的时候已经保证了这一点。 this.codeHead.AddBefore(node); this.codeHead = node; }
/// <summary> /// 清空缓存中的所有对象。 /// </summary> public void Clear() { cacheDict.Clear(); head = codeHead = null; count = 0; }