/// <summary>
        /// Looks for a value for the matching <paramref name="key"/>. If not found,
        /// calls <paramref name="valueGenerator"/> to retrieve the value and add it to
        /// the cache.
        /// </summary>
        /// <param name="key">
        /// The key of the value to look up.
        /// </param>
        /// <param name="valueGenerator">
        /// Generates a value if one isn't found.
        /// </param>
        /// <returns>
        /// The requested value.
        /// </returns>
        public TValue Get(TKey key, Func <TValue> valueGenerator)
        {
            lock (this.cacheMap)
            {
                LinkedListNode <LRUNode> node;
                TValue value;
                if (this.cacheMap.TryGetValue(key, out node))
                {
                    value = node.Value.Value;
                    this.lruList.Remove(node);
                    this.lruList.AddLast(node);
                }
                else
                {
                    value = valueGenerator();
                    if (this.cacheMap.Count >= this.Capacity)
                    {
                        this.RemoveFirst();
                    }

                    LRUNode cacheItem = new LRUNode(key, value);
                    node = new LinkedListNode <LRUNode>(cacheItem);
                    this.lruList.AddLast(node);
                    this.cacheMap.Add(key, node);
                }

                return(value);
            }
        }
Exemple #2
0
 public void Put(int key, int value)
 {
     if (_capacity == 0)
     {
         return;
     }
     if (_cache.TryGetValue(key, out var node))
     {
         RemoveNode(node);
         AddToHead(node);
         node.Value = value;
     }
     else
     {
         if (_capacity == _cache.Count)
         {
             node = PopTail();
             _cache.Remove(node.Key);
         }
         node = new LRUNode {
             Key = key, Value = value
         };
         _cache[key] = node;
         AddToHead(node);
     }
 }
Exemple #3
0
    public int Get(int key) {
        if (!map.ContainsKey(key)) return -1;
		LRUNode node = map[key];
		doubleLinkedList.RemoveNode(node);
		doubleLinkedList.AddToTop(node);
		return node.Value;
    }
Exemple #4
0
        public LRUNode RemoveLRUNode()
        {
            LRUNode target = Tail.Previous;

            RemoveNode(target);
            return(target);
        }
Exemple #5
0
		public LRUDoubleLinkedList()
		{
			Head = new LRUNode();
			Tail = new LRUNode();
			Head.Next = Tail;
			Tail.Previous = Head;
		}
Exemple #6
0
 public void RemoveNode(LRUNode node)
 {
     node.Previous.Next = node.Next;
     node.Next.Previous = node.Previous;
     node.Next          = null;
     node.Previous      = null;
 }
Exemple #7
0
 public void AddToTop(LRUNode node)
 {
     node.Next          = Head.Next;
     Head.Next.Previous = node;
     node.Previous      = Head;
     Head.Next          = node;
 }
Exemple #8
0
 private void AddToHead(LRUNode node)
 {
     _head.Next.Prev = node;
     node.Next       = _head.Next;
     node.Prev       = _head;
     _head.Next      = node;
 }
Exemple #9
0
        public void Add(int key, int value)
        {
            // just need to update value and move it to the top
            if (map.ContainsKey(key))
            {
                LRUNode node = map[key];
                doubleLinkedList.RemoveNode(node);
                node.Value = value;
                doubleLinkedList.AddToTop(node);
            }
            else
            {
                // if cache is full, then remove the least recently used node
                if (count == capacity)
                {
                    LRUNode lru = doubleLinkedList.RemoveLRUNode();
                    map.Remove(lru.Key);
                    count--;
                }

                // add a new node
                LRUNode node = new LRUNode(key, value);
                doubleLinkedList.AddToTop(node);
                map[key] = node;
                count++;
            }
        }
 public TValue this[TKey key]
 {
     get
     {
         LRUNode node = FindNode(key) ?? throw new KeyNotFoundException();
         return(node.Value);
     }
     set => AddOrSet(key, value);
 public LRULinkedMap(int capacity, IEqualityComparer <TKey> comparer)
 {
     m_Buckets  = new LRUNode[HashUtility.GetPrimeCapacity(capacity)];
     m_Comparer = comparer ?? EqualityComparer <TKey> .Default;
     m_Count    = 0;
     m_Version  = 0;
     m_Head     = null;
     m_Tail     = null;
     m_FreeList = null;
 }
 /// <summary>
 /// Retrieves the key within the cache if contained.
 /// </summary>
 /// <param name="key"></param>
 /// <returns></returns>
 public V get(K key)
 {
     if (map.ContainsKey(key))
     {
         LRUNode node = map[key];
         remove(node);
         add(node);
         return(node.value);
     }
     return(default(V));
 }
        public override string ToString()
        {
            StringBuilder sb   = new StringBuilder();
            LRUNode       iter = head;

            while (iter != null)
            {
                sb.Append("[" + iter.value.ToString() + "]");
                iter = iter.next;
            }
            return(sb.ToString());
        }
Exemple #14
0
        public void Add(K key, V val)
        {
            while (total >= capacity)
            {
                remove();
            }
            LRUNode cacheItem             = new LRUNode(key, val);
            LinkedListNode <LRUNode> node = new LinkedListNode <LRUNode>(cacheItem);

            lruList.AddLast(node);
            cacheMap.Add(key, node);
            total += ItemCount(val);
        }
        /// <summary>
        /// Retrieves the given value at the given index in the list
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public V get(int index)
        {
            if (index > map.Count)
            {
                return(default(V));
            }
            LRUNode iter = head;

            while (iter != null && index > 0)
            {
                iter = iter.next;
                index--;
            }
            return(iter.value);
        }
        /// <summary>
        /// Adds the specified key and value to the dictionary.
        /// </summary>
        /// <param name="key">
        /// The key of the element to add.
        /// </param>
        /// <param name="value">
        /// The value of the element to add. The value can be null for reference types.
        /// </param>
        public void Add(TKey key, TValue value)
        {
            lock (this.cacheMap)
            {
                if (this.cacheMap.Count >= this.Capacity)
                {
                    this.RemoveFirst();
                }

                LRUNode cacheItem             = new LRUNode(key, value);
                LinkedListNode <LRUNode> node =
                    new LinkedListNode <LRUNode>(cacheItem);
                this.lruList.AddLast(node);
                this.cacheMap.Add(key, node);
            }
        }
 // Sets the head of the cache
 private void add(LRUNode node)
 {
     if (head == null || tail == null)
     {
         head = node;
         tail = node;
         map.Add(node.key, node);
     }
     else
     {
         node.previous = null;
         node.next     = head;
         head.previous = node;
         head          = node;
         map.Add(node.key, node);
     }
 }
Exemple #18
0
 public void Set(K key, V value)
 {
     if (itemMap.TryGetValue(key, out LRUNode <K, V> existingNode))
     {
         LRUNode <K, V> node = existingNode;
         node.value = value;
         if (existingNode == head)
         {
             return;
         }
         else if (existingNode == tail)
         {
             node = EvictTail(key, value);
         }
         else
         {
             node.prev.next = node.next;
             node.next.prev = node.prev;
         }
         Promote(node);
     }
     else if (Size == 0)
     {
         LRUNode <K, V> headNode = new LRUNode <K, V>(key, value);
         head = tail = headNode;
         itemMap.TryAdd(key, headNode);
         Size++;
     }
     else if (Size == Capacity)
     {
         itemMap.TryRemove(tail.key, out LRUNode <K, V> _);
         LRUNode <K, V> oldTail = EvictTail(key, value);
         Promote(oldTail);
         itemMap.TryAdd(key, oldTail);
     }
     else
     {
         LRUNode <K, V> node = new LRUNode <K, V>(key, value);
         itemMap.TryAdd(key, node);
         Size++;
         Promote(node);
     }
 }
        public void Get_ShouldTakeANonLeafNode_AndPromoteIt_When_Called()
        {
            subject.Set(1, 10);
            subject.Set(2, 20);
            subject.Set(3, 30);
            subject.Set(4, 40);

            subject.Get(2);

            LoadInternalPointers();

            int[] expectedItemOrder = { 20, 40, 30, 10 };
            int   index             = 0;

            LRUNode <int, int> node = head;

            while (node != null)
            {
                Assert.Equal(expectedItemOrder[index++], node.value);
                node = node.next;
            }
        }
        public void Set_ShouldEnsureProperOrdering_Even_When_WeAreOverCapacity()
        {
            int[] items             = { 10, 50, 40, 30, 5, 10, 20, 44, 25, 29, 90, 84, 33, 22, 5 };
            int[] expectedItemOrder = items.Reverse().Distinct().Take(PreferredCapacity).ToArray();

            foreach (int item in items)
            {
                subject.Set(item, item);
            }

            LoadInternalPointers();

            int index = 0;

            LRUNode <int, int> node = head;

            while (node != null)
            {
                Assert.Equal(expectedItemOrder[index++], node.value);
                node = node.next;
            }
        }
Exemple #21
0
    public void Put(int key, int value) {
        if (map.ContainsKey(key))
			{
				LRUNode node = map[key];
				doubleLinkedList.RemoveNode(node);
				node.Value = value;
				doubleLinkedList.AddToTop(node);
			}
			else
			{
				if (count==capacity) {
					LRUNode lru = doubleLinkedList.RemoveLRUNode();
					map.Remove(lru.Key);
					count--;
				}

				LRUNode node = new LRUNode(key, value);
				doubleLinkedList.AddToTop(node);
				map[key] = node;
				count++;
			}
    }
 /// <summary>
 /// Adds the key value pair to the cache, returns true if key is precent in the cache
 /// and returns false if there is no mapping and the key was to be inserted
 /// false if the
 /// </summary>
 /// <param name="key"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public bool put(K key, V value)
 {
     if (map.ContainsKey(key))
     {
         LRUNode old = map[key];
         old.value = value;
         remove(old);
         add(old);
         return(true);
     }
     else
     {
         // if adding one would put it over limit, dont add
         if (map.Count + 1 > limit)
         {
             remove(tail);
         }
         if (map.Count < limit)
         {
             add(new LRUNode(key, value));
         }
         return(false);
     }
 }
        public void Set_ShouldAddItemsAsTheyArrive_And_PromoteAsNecessary_When_Called()
        {
            int[] items = new int[] { 10, 20, 5, 6, 10, 60 };

            foreach (int item in items)
            {
                subject.Set(item, item);
            }

            LoadInternalPointers();

            int[] expectedItemOrder = new int[] { 60, 10, 6, 5, 20 };
            int   index             = 0;

            Assert.Equal(expectedItemOrder.Length, itemMap.Count);

            LRUNode <int, int> node = head;

            while (node != null)
            {
                Assert.Equal(expectedItemOrder[index++], node.value);
                node = node.next;
            }
        }
 // removes all references of the given node within
 private void remove(LRUNode node)
 {
     if (node == null)
     {
         return;
     }
     if (node.previous != null)
     {
         node.previous.next = node.next;
     }
     if (node.next != null)
     {
         node.next.previous = node.previous;
     }
     if (node == tail)
     {
         tail = tail.previous;
     }
     if (node == head)
     {
         head = head.next;
     }
     map.Remove(node.key);
 }
 private void LoadInternalPointers()
 {
     itemMap = TestHelper.Helper.GetFieldValueFromInstance <ConcurrentDictionary <int, LRUNode <int, int> > >("itemMap", false, false, subject);
     head    = TestHelper.Helper.GetFieldValueFromInstance <LRUNode <int, int> >("head", false, false, subject);
     tail    = TestHelper.Helper.GetFieldValueFromInstance <LRUNode <int, int> >("tail", false, false, subject);
 }
Exemple #26
0
 private void RemoveNode(LRUNode node)
 {
     node.Prev.Next = node.Next;
     node.Next.Prev = node.Prev;
 }