2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 using System.Collections.Generic;
21 namespace Mono.Lucene.Net.Util.Cache
23 public class SimpleLRUCache : SimpleMapCache
26 /// The maximum number of items to cache.
31 /// The list to efficiently maintain the LRU state.
33 private LinkedList<ListValueEntry> list;
36 /// The dictionary to hash into any location in the list.
38 private Dictionary<object, LinkedListNode<ListValueEntry>> lookup;
41 /// The node instance to use/re-use when adding an item to the cache.
43 private LinkedListNode<ListValueEntry> openNode;
45 public SimpleLRUCache(int Capacity)
47 this.capacity = Capacity;
48 this.list = new LinkedList<ListValueEntry>();
49 this.lookup = new Dictionary<object, LinkedListNode<ListValueEntry>>(Capacity + 1);
50 this.openNode = new LinkedListNode<ListValueEntry>(new ListValueEntry(null, null));
53 public override void Put(object Key, object Value)
57 this.openNode.Value.ItemKey = Key;
58 this.openNode.Value.ItemValue = Value;
59 this.list.AddFirst(this.openNode);
60 this.lookup.Add(Key, this.openNode);
62 if (this.list.Count > this.capacity)
64 // last node is to be removed and saved for the next addition to the cache
65 this.openNode = this.list.Last;
67 // remove from list & dictionary
68 this.list.RemoveLast();
69 this.lookup.Remove(this.openNode.Value.ItemKey);
73 // still filling the cache, create a new open node for the next time
74 this.openNode = new LinkedListNode<ListValueEntry>(new ListValueEntry(null, null));
79 public override object Get(object Key)
81 LinkedListNode<ListValueEntry> node = null;
82 if(!this.lookup.TryGetValue(Key, out node))
86 this.list.Remove(node);
87 this.list.AddFirst(node);
88 return node.Value.ItemValue;
92 /// Container to hold the key and value to aid in removal from
93 /// the <see cref="lookup"/> dictionary when an item is removed from cache.
97 internal object ItemValue;
98 internal object ItemKey;
100 internal ListValueEntry(object key, object value)
103 this.ItemValue = value;
109 #region NOT_USED_FROM_JLCA_PORT
113 // This is the oringal port as it was generated via JLCA.
114 // This code is not used. It's here for referance only.
118 /// <summary> Simple LRU cache implementation that uses a LinkedHashMap.
119 /// This cache is not synchronized, use {@link Cache#SynchronizedCache(Cache)}
123 public class SimpleLRUCache:SimpleMapCache
125 private class AnonymousClassLinkedHashMap : LinkedHashMap
127 public AnonymousClassLinkedHashMap(SimpleLRUCache enclosingInstance)
129 InitBlock(enclosingInstance);
131 private void InitBlock(SimpleLRUCache enclosingInstance)
133 this.enclosingInstance = enclosingInstance;
135 private SimpleLRUCache enclosingInstance;
136 public SimpleLRUCache Enclosing_Instance
140 return enclosingInstance;
144 protected internal virtual bool RemoveEldestEntry(System.Collections.DictionaryEntry eldest)
146 return size() > Enclosing_Instance.cacheSize;
149 private const float LOADFACTOR = 0.75f;
151 private int cacheSize;
153 /// <summary> Creates a last-recently-used cache with the specified size. </summary>
154 public SimpleLRUCache(int cacheSize):base(null)
156 this.cacheSize = cacheSize;
157 int capacity = (int) System.Math.Ceiling(cacheSize / LOADFACTOR) + 1;
159 base.map = new AnonymousClassLinkedHashMap(this, capacity, LOADFACTOR, true);