-
Notifications
You must be signed in to change notification settings - Fork 35
/
lru.go
62 lines (50 loc) · 1.42 KB
/
lru.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package tinylfu
import "github.com/dgryski/go-tinylfu/internal/list"
// Cache is an LRU cache. It is not safe for concurrent access.
type lruCache[K comparable, V any] struct {
data map[K]*list.Element[*slruItem[K, V]]
cap int
ll *list.List[*slruItem[K, V]]
}
func newLRU[K comparable, V any](cap int, data map[K]*list.Element[*slruItem[K, V]]) *lruCache[K, V] {
return &lruCache[K, V]{
data: data,
cap: cap,
ll: list.New[*slruItem[K, V]](),
}
}
// Get returns a value from the cache
func (lru *lruCache[K, V]) get(v *list.Element[*slruItem[K, V]]) {
lru.ll.MoveToFront(v)
}
// Set sets a value in the cache
func (lru *lruCache[K, V]) add(newitem slruItem[K, V]) (oitem slruItem[K, V], evicted bool) {
if lru.ll.Len() < lru.cap {
lru.data[newitem.key] = lru.ll.PushFront(&newitem)
return slruItem[K, V]{}, false
}
// reuse the tail item
e := lru.ll.Back()
item := e.Value
delete(lru.data, item.key)
oitem = *item
*item = newitem
lru.data[item.key] = e
lru.ll.MoveToFront(e)
return oitem, true
}
// Len returns the total number of items in the cache
func (lru *lruCache[K, V]) Len() int {
return len(lru.data)
}
// Remove removes an item from the cache, returning the item and a boolean indicating if it was found
func (lru *lruCache[K, V]) Remove(key K) (V, bool) {
v, ok := lru.data[key]
if !ok {
return *new(V), false
}
item := v.Value
lru.ll.Remove(v)
delete(lru.data, key)
return item.value, true
}