Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
SimpleLRUCache.cs
Go to the documentation of this file.
1 /*
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
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 
18 using System;
19 using System.Collections.Generic;
20 
21 namespace Lucene.Net.Util.Cache
22 {
23  public class SimpleLRUCache<TKey, TValue> : SimpleMapCache<TKey, TValue>
24  {
25  /// <summary>
26  /// The maximum number of items to cache.
27  /// </summary>
28  private int capacity;
29 
30  /// <summary>
31  /// The list to efficiently maintain the LRU state.
32  /// </summary>
33  private LinkedList<ListValueEntry<TKey, TValue>> list;
34 
35  /// <summary>
36  /// The dictionary to hash into any location in the list.
37  /// </summary>
38  private Dictionary<TKey, LinkedListNode<ListValueEntry<TKey, TValue>>> lookup;
39 
40  /// <summary>
41  /// The node instance to use/re-use when adding an item to the cache.
42  /// </summary>
43  private LinkedListNode<ListValueEntry<TKey, TValue>> openNode;
44 
45  public SimpleLRUCache(int Capacity)
46  {
47  this.capacity = Capacity;
48  this.list = new LinkedList<ListValueEntry<TKey, TValue>>();
49  this.lookup = new Dictionary<TKey, LinkedListNode<ListValueEntry<TKey, TValue>>>(Capacity + 1);
50  this.openNode = new LinkedListNode<ListValueEntry<TKey, TValue>>(new ListValueEntry<TKey, TValue>(default(TKey), default(TValue)));
51  }
52 
53  public override void Put(TKey Key, TValue Value)
54  {
55  if (Get(Key) == null)
56  {
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);
61 
62  if (this.list.Count > this.capacity)
63  {
64  // last node is to be removed and saved for the next addition to the cache
65  this.openNode = this.list.Last;
66 
67  // remove from list & dictionary
68  this.list.RemoveLast();
69  this.lookup.Remove(this.openNode.Value.ItemKey);
70  }
71  else
72  {
73  // still filling the cache, create a new open node for the next time
74  this.openNode = new LinkedListNode<ListValueEntry<TKey, TValue>>(new ListValueEntry<TKey, TValue>(default(TKey), default(TValue)));
75  }
76  }
77  }
78 
79  public override TValue Get(object Key)
80  {
81  LinkedListNode<ListValueEntry<TKey, TValue>> node = null;
82  if (!this.lookup.TryGetValue((TKey)Key, out node))
83  {
84  return default(TValue);
85  }
86  this.list.Remove(node);
87  this.list.AddFirst(node);
88  return node.Value.ItemValue;
89  }
90 
91  /// <summary>
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.
94  /// </summary>
95  class ListValueEntry<K, V> where K : TKey
96  where V : TValue
97  {
98  internal V ItemValue;
99  internal K ItemKey;
100 
101  internal ListValueEntry(K key, V value)
102  {
103  this.ItemKey = key;
104  this.ItemValue = value;
105  }
106  }
107  }
108 
109 
110 #region NOT_USED_FROM_JLCA_PORT
111 /*
112 
113  //
114  // This is the oringal port as it was generated via JLCA.
115  // This code is not used. It's here for referance only.
116  //
117 
118 
119  /// <summary> Simple LRU cache implementation that uses a LinkedHashMap.
120  /// This cache is not synchronized, use <see cref="Cache.SynchronizedCache(Cache)" />
121  /// if needed.
122  ///
123  /// </summary>
124  public class SimpleLRUCache:SimpleMapCache
125  {
126  private class AnonymousClassLinkedHashMap : LinkedHashMap
127  {
128  public AnonymousClassLinkedHashMap(SimpleLRUCache enclosingInstance)
129  {
130  InitBlock(enclosingInstance);
131  }
132  private void InitBlock(SimpleLRUCache enclosingInstance)
133  {
134  this.enclosingInstance = enclosingInstance;
135  }
136  private SimpleLRUCache enclosingInstance;
137  public SimpleLRUCache Enclosing_Instance
138  {
139  get
140  {
141  return enclosingInstance;
142  }
143 
144  }
145  protected internal virtual bool RemoveEldestEntry(System.Collections.DictionaryEntry eldest)
146  {
147  return size() > Enclosing_Instance.cacheSize;
148  }
149  }
150  private const float LOADFACTOR = 0.75f;
151 
152  private int cacheSize;
153 
154  /// <summary> Creates a last-recently-used cache with the specified size. </summary>
155  public SimpleLRUCache(int cacheSize):base(null)
156  {
157  this.cacheSize = cacheSize;
158  int capacity = (int) System.Math.Ceiling(cacheSize / LOADFACTOR) + 1;
159 
160  base.map = new AnonymousClassLinkedHashMap(this, capacity, LOADFACTOR, true);
161  }
162  }
163 */
164 #endregion
165 
166 }