Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / tools / monkeydoc / Lucene.Net / Lucene.Net / Util / Cache / SimpleLRUCache.cs
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 Mono.Lucene.Net.Util.Cache
22 {
23     public class SimpleLRUCache : SimpleMapCache
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> list;
34
35         /// <summary>
36         /// The dictionary to hash into any location in the list.
37         /// </summary>
38         private Dictionary<object, LinkedListNode<ListValueEntry>> 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> openNode;
44
45         public SimpleLRUCache(int Capacity)
46         {
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));
51         }
52
53         public override void Put(object Key, object 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>(new ListValueEntry(null, null));
75                 }
76             }
77         }
78
79         public override object Get(object Key)
80         {
81             LinkedListNode<ListValueEntry> node = null;
82             if(!this.lookup.TryGetValue(Key, out node))
83             {
84                 return null;
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
96         {
97             internal object ItemValue;
98             internal object ItemKey;
99
100             internal ListValueEntry(object key, object value)
101             {
102                 this.ItemKey = key;
103                 this.ItemValue = value;
104             }
105         }
106     }
107
108
109 #region NOT_USED_FROM_JLCA_PORT
110 /*
111   
112  //
113  // This is the oringal port as it was generated via JLCA.
114  // This code is not used.  It's here for referance only.
115  //
116   
117
118         /// <summary> Simple LRU cache implementation that uses a LinkedHashMap.
119         /// This cache is not synchronized, use {@link Cache#SynchronizedCache(Cache)}
120         /// if needed.
121         /// 
122         /// </summary>
123         public class SimpleLRUCache:SimpleMapCache
124         {
125                 private class AnonymousClassLinkedHashMap : LinkedHashMap
126                 {
127                         public AnonymousClassLinkedHashMap(SimpleLRUCache enclosingInstance)
128                         {
129                                 InitBlock(enclosingInstance);
130                         }
131                         private void  InitBlock(SimpleLRUCache enclosingInstance)
132                         {
133                                 this.enclosingInstance = enclosingInstance;
134                         }
135                         private SimpleLRUCache enclosingInstance;
136                         public SimpleLRUCache Enclosing_Instance
137                         {
138                                 get
139                                 {
140                                         return enclosingInstance;
141                                 }
142                                 
143                         }
144                         protected internal virtual bool RemoveEldestEntry(System.Collections.DictionaryEntry eldest)
145                         {
146                                 return size() > Enclosing_Instance.cacheSize;
147                         }
148                 }
149                 private const float LOADFACTOR = 0.75f;
150                 
151                 private int cacheSize;
152                 
153                 /// <summary> Creates a last-recently-used cache with the specified size. </summary>
154                 public SimpleLRUCache(int cacheSize):base(null)
155                 {
156                         this.cacheSize = cacheSize;
157                         int capacity = (int) System.Math.Ceiling(cacheSize / LOADFACTOR) + 1;
158                         
159                         base.map = new AnonymousClassLinkedHashMap(this, capacity, LOADFACTOR, true);
160                 }
161         }
162 */
163 #endregion
164
165 }