Example #1
0
 /// <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;
 }
Example #2
0
 /// <summary>
 /// 清空缓存中的所有对象。
 /// </summary>
 public void Clear()
 {
     lock (cacheLock)
     {
         cacheDict.Clear();
         head  = codeHead = null;
         count = 0;
     }
 }
Example #3
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);
            }
        }
Example #4
0
 /// <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;
 }
Example #5
0
 /// <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;
         }
     }
 }
Example #6
0
 /// <summary>
 /// 将指定的节点添加到链表冷端的头部,链表操作本身是非线程安全的。
 /// </summary>
 /// <param name="node">要添加的节点。</param>
 private void AddCodeFirst(LruNode <TKey, TValue> node)
 {
     Debug.Assert(codeHead != null);
     this.codeHead.AddBefore(node);
     this.codeHead = node;
 }