/
cache-map-lru.go
80 lines (70 loc) · 1.39 KB
/
cache-map-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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package gofnext
import (
"container/list"
"sync"
"time"
)
type cachedNode struct {
val interface{}
createdAt time.Time
err error
element *list.Element
}
type cacheLru struct {
list *list.List
listMap *sync.Map
maxSize int
mu sync.RWMutex
ttl time.Duration
}
func NewCacheLru(maxSize int) *cacheLru {
if maxSize <= 0 {
maxSize = 100
}
return &cacheLru{
maxSize: maxSize,
list: list.New(),
listMap: &sync.Map{},
}
}
func (m *cacheLru) Store(key, value any, err error) {
m.mu.Lock()
defer m.mu.Unlock()
el := cachedNode{
val: value,
createdAt: time.Now(),
err: err,
}
if m.maxSize > 0 && m.list.Len() >= m.maxSize {
elInter := m.list.Back()
m.list.Remove(elInter)
m.listMap.Delete(elInter.Value)
}
el.element = m.list.PushFront(key)
m.listMap.Store(key, &el)
}
func (m *cacheLru) Load(key any) (value any, existed bool, err error) {
m.mu.Lock()
defer m.mu.Unlock()
elInter, existed := m.listMap.Load(key)
if existed {
el := elInter.(*cachedNode)
if m.ttl > 0 && time.Since(el.createdAt) > m.ttl {
m.listMap.Delete(key)
m.list.Remove(el.element)
existed = false
} else {
// move to front
m.list.MoveToFront(el.element)
return el.val, existed, el.err
}
}
return
}
func (m *cacheLru) SetTTL(ttl time.Duration) CacheMap {
m.ttl = ttl
return m
}
func (m *cacheLru) NeedMarshal() bool {
return false
}