ln.collections/ln.collections/Cache.cs

97 lines
1.6 KiB
C#

using System;
namespace ln.collections
{
public class Cache<K,V>
{
public int Count => values.Count;
BTree<K, V> values;
BTree<K, LinkedListItem<K>> itemTree;
LinkedList<K> items = new LinkedList<K>();
int maxCacheSize = 4096;
public Cache()
{
values = new BTree<K, V>();
itemTree = new BTree<K, LinkedListItem<K>>();
}
public Cache(Comparison<K> compare)
{
values = new BTree<K, V>(compare);
itemTree = new BTree<K, LinkedListItem<K>>(compare);
}
public int MaxCacheSize
{
get => maxCacheSize;
set {
maxCacheSize = value;
while (maxCacheSize < values.Count)
{
Forget();
}
}
}
public void Clear()
{
values.Clear();
itemTree.Clear();
items.Clear();
}
public bool TryGet(K key,out V value)
{
return values.TryGet(key, out value);
}
public void Forget()
{
lock (this)
{
Forget(items.FirstItem);
}
}
public void Forget(K key)
{
lock (this)
{
if (itemTree.TryGet(key,out LinkedListItem<K> item))
Forget(item);
}
}
private void Forget(LinkedListItem<K> item)
{
if (item == null)
return;
values.Remove(item.Value);
itemTree.Remove(item.Value);
items.Remove(item);
}
public void Ensure(K key,V value)
{
lock (this)
{
if (!itemTree.TryGet(key, out LinkedListItem<K> item))
{
item = new LinkedListItem<K>(key);
values.Add(key,value);
}
Ensure(item);
}
}
private void Ensure(LinkedListItem<K> item)
{
if (!item.IsLinked)
itemTree.Add(item.Value, item);
items.Add(item);
}
}
}