5 // Miguel de Icaza (miguel@gnome.org)
6 // Andres G. Aragoneses (andres@7digital.com)
8 // Copyright 2010 Miguel de Icaza
9 // Copyright 2013 7digital Media Ltd.
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31 using System.Collections.Generic;
33 namespace System.Web.Configuration {
35 class LruCache<TKey, TValue> {
36 Dictionary<TKey, LinkedListNode <TValue>> dict;
37 Dictionary<LinkedListNode<TValue>, TKey> revdict;
38 LinkedList<TValue> list;
41 bool eviction_warning_shown;
45 internal string EvictionWarning { set; private get; }
47 public LruCache (int entryLimit)
49 entry_limit = entryLimit;
50 dict = new Dictionary<TKey, LinkedListNode<TValue>> ();
51 revdict = new Dictionary<LinkedListNode<TValue>, TKey> ();
52 list = new LinkedList<TValue> ();
55 //for debugging: public int Count { get { return dict.Count; } }
63 var key = revdict [last];
66 revdict.Remove (last);
68 DisposeValue (last.Value);
71 if (!String.IsNullOrEmpty (EvictionWarning) && !eviction_warning_shown && (evictions >= entry_limit)) {
72 Console.Error.WriteLine ("WARNING: " + EvictionWarning);
73 eviction_warning_shown = true;
79 foreach (var element in list) {
80 DisposeValue (element);
86 eviction_warning_shown = false;
90 void DisposeValue (TValue value)
92 if (value is IDisposable) {
93 ((IDisposable)value).Dispose ();
97 public bool TryGetValue (TKey key, out TValue value)
99 LinkedListNode<TValue> node;
101 if (dict.TryGetValue (key, out node)){
103 list.AddFirst (node);
108 value = default (TValue);
112 public void Add (TKey key, TValue value)
114 LinkedListNode<TValue> node;
116 if (dict.TryGetValue (key, out node)){
118 // If we already have a key, move it to the front
120 list.AddFirst (node);
122 // Remove the old value
123 DisposeValue (node.Value);
129 if (dict.Count >= entry_limit)
133 node = new LinkedListNode<TValue> (value);
134 list.AddFirst (node);
136 revdict [node] = key;
139 public override string ToString ()
141 return "LRUCache dict={0} revdict={1} list={2}";