Skip to content

Commit 55b274a

Browse files
committed
feat: created simple LRU cache
1 parent 764eb0f commit 55b274a

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

pkg/cache/lru.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package lru
2+
3+
import "sync"
4+
5+
type node struct {
6+
key string
7+
val string
8+
prev *node
9+
next *node
10+
}
11+
12+
type Cache interface {
13+
Get(string) string
14+
Set(string, string)
15+
}
16+
17+
type LRU struct {
18+
maxCapacity int
19+
capacity int
20+
cache map[string]*node
21+
head *node
22+
tail *node
23+
mutex sync.Mutex
24+
}
25+
26+
func (lru *LRU) Get(key string) string {
27+
lru.mutex.Lock()
28+
defer lru.mutex.Unlock()
29+
n := lru.cache[key]
30+
if n == nil {
31+
return ""
32+
}
33+
34+
lru.remove(n)
35+
lru.insertRight(n)
36+
37+
return n.val
38+
}
39+
40+
func (lru *LRU) Set(key, value string) {
41+
lru.mutex.Lock()
42+
defer lru.mutex.Unlock()
43+
if n := lru.cache[key]; n != nil {
44+
lru.remove(n)
45+
}
46+
47+
n := &node{key: key, val: value}
48+
lru.cache[key] = n
49+
lru.insertRight(n)
50+
51+
// evict
52+
if lru.capacity > lru.maxCapacity {
53+
delete(lru.cache, lru.tail.next.key)
54+
lru.remove(lru.tail.next)
55+
}
56+
57+
}
58+
59+
func (lru *LRU) insertRight(n *node) {
60+
prev := lru.head.prev
61+
prev.next = n
62+
n.prev = prev
63+
n.next = lru.head
64+
lru.head.prev = n
65+
}
66+
67+
func (lru *LRU) remove(n *node) {
68+
prev := n.prev
69+
nxt := n.next
70+
prev.next = nxt
71+
nxt.prev = prev
72+
n.prev = nil
73+
n.next = nil
74+
lru.capacity--
75+
}
76+
77+
func Make(maxCapacity int) Cache {
78+
head := &node{}
79+
tail := &node{}
80+
tail.next = head
81+
head.prev = tail
82+
return &LRU{
83+
maxCapacity: maxCapacity,
84+
capacity: 0,
85+
cache: make(map[string]*node),
86+
head: head,
87+
tail: tail,
88+
}
89+
}

0 commit comments

Comments
 (0)