/// <summary> /// 向当前节点之前添加新节点。 /// </summary> /// <param name="node">要添加的新节点。</param> public void AddBefore(LruNode <TKey, TValue> node) { node.Next = this; node.Prev = this.Prev; this.Prev.Next = node; this.Prev = node; }
/// <summary> /// 清空缓存中的所有对象。 /// </summary> public void Clear() { lock (cacheLock) { cacheDict.Clear(); head = codeHead = null; count = 0; } }
/// <summary> /// 将指定的键和对象添加到缓存中,并返回添加的节点。 /// </summary> /// <param name="key">要添加的对象的键。</param> /// <param name="value">要添加的对象。</param> /// <param name="force">是否要强制更新已有键相应的对象。</param> private LruNode <TKey, TValue> AddInternal(TKey key, Lazy <TValue> value, bool force) { LruNode <TKey, TValue> newNode = new LruNode <TKey, TValue>(key, value); LruNode <TKey, TValue> node = cacheDict.AddOrUpdate(key, newNode, (k, v) => { if (force) { v.Value = value; } return(v); }); if (node != newNode) { return(node); } // 将节点添加到链表中。 lock (cacheLock) { if (node.VisitCount != -1) { if (count < maxSize) { // 将新节点添加到热端的头。 AddHotFirst(newNode); 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 移除。 if (!comparer.Equals(head.Prev.Key, key)) { this.cacheDict.TryRemove(head.Prev.Key, out node); } this.Remove(head.Prev); // 将新节点添加到冷端的头。 this.AddCodeFirst(newNode); } } return(newNode); } }
/// <summary> /// 将指定的节点添加到链表热端的头部,链表操作本身是非线程安全的。 /// </summary> /// <param name="node">要添加的节点。</param> private void AddHotFirst(LruNode <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(LruNode <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="node">要添加的节点。</param> private void AddCodeFirst(LruNode <TKey, TValue> node) { Debug.Assert(codeHead != null); this.codeHead.AddBefore(node); this.codeHead = node; }