Files
Explorer-Workbench/src/Explorer.Application/LruCache.cs

64 lines
1.7 KiB
C#

namespace Explorer.Application;
public sealed class LruCache<TKey, TValue>
where TKey : notnull
{
private readonly int _capacity;
private readonly Dictionary<TKey, LinkedListNode<(TKey Key, TValue Value)>> _map;
private readonly LinkedList<(TKey Key, TValue Value)> _order;
private readonly object _gate = new();
public LruCache(int capacity)
{
ArgumentOutOfRangeException.ThrowIfLessThan(capacity, 1);
_capacity = capacity;
_map = new Dictionary<TKey, LinkedListNode<(TKey, TValue)>>(capacity);
_order = new LinkedList<(TKey, TValue)>();
}
public int Count
{
get { lock (_gate) return _map.Count; }
}
public bool TryGet(TKey key, out TValue value)
{
lock (_gate)
{
if (_map.TryGetValue(key, out var node))
{
_order.Remove(node);
_order.AddFirst(node);
value = node.Value.Value;
return true;
}
}
value = default!;
return false;
}
public void Set(TKey key, TValue value)
{
lock (_gate)
{
if (_map.TryGetValue(key, out var existing))
{
_order.Remove(existing);
existing.Value = (key, value);
_order.AddFirst(existing);
return;
}
var node = _order.AddFirst((key, value));
_map[key] = node;
while (_map.Count > _capacity)
{
var last = _order.Last!;
_order.RemoveLast();
_map.Remove(last.Value.Key);
}
}
}
}