lru.go
⎇
Raw
1package service
2
3import (
4 "container/list"
5 "sync"
6)
7
8// lru is a fixed-size map keyed by path. Only for values that are safe to lose:
9// an eviction means the work is redone, never that correctness changes.
10type lru[V any] struct {
11 mu sync.Mutex
12 maxSize int
13 order *list.List // front is most recently used
14 entries map[string]*list.Element
15}
16
17type lruEntry[V any] struct {
18 key string
19 val V
20}
21
22func newLRU[V any](maxSize int) *lru[V] {
23 // Below 1, each entry is evicted as it is stored: a silent miss every time.
24 return &lru[V]{
25 maxSize: max(maxSize, 1),
26 order: list.New(),
27 entries: make(map[string]*list.Element),
28 }
29}
30
31func (c *lru[V]) Get(key string) (V, bool) {
32 c.mu.Lock()
33 defer c.mu.Unlock()
34
35 el, ok := c.entries[key]
36 if !ok {
37 var zero V
38 return zero, false
39 }
40 c.order.MoveToFront(el)
41 return el.Value.(*lruEntry[V]).val, true
42}
43
44func (c *lru[V]) Put(key string, val V) {
45 c.mu.Lock()
46 defer c.mu.Unlock()
47
48 if el, ok := c.entries[key]; ok {
49 el.Value.(*lruEntry[V]).val = val
50 c.order.MoveToFront(el)
51 return
52 }
53
54 c.entries[key] = c.order.PushFront(&lruEntry[V]{key: key, val: val})
55
56 if c.order.Len() > c.maxSize {
57 oldest := c.order.Back()
58 c.order.Remove(oldest)
59 delete(c.entries, oldest.Value.(*lruEntry[V]).key)
60 }
61}
62
63func (c *lru[V]) Delete(key string) {
64 c.mu.Lock()
65 defer c.mu.Unlock()
66
67 if el, ok := c.entries[key]; ok {
68 c.order.Remove(el)
69 delete(c.entries, key)
70 }
71}
72