-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlru.go
More file actions
78 lines (69 loc) · 1.55 KB
/
lru.go
File metadata and controls
78 lines (69 loc) · 1.55 KB
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
package sift
import "container/list"
// not thread safe
type Lru interface {
Add(interface{}, interface{})
Get(interface{}) (interface{}, bool)
RemoveOldest()
SetOnEvicted(func(interface{}, interface{}))
}
type lruEntry struct {
Value interface{}
Key interface{}
}
type ClassicLru struct {
MaxLen int
ll *list.List
cache map[interface{}]*list.Element
OnEvicted func(key interface{}, value interface{}) //evicted callback used for free memory
}
func NewClassicLru(MaxLen int) Lru {
return &ClassicLru{
MaxLen:MaxLen,
ll:list.New(),
cache:make(map[interface{}]*list.Element),
}
}
func (cl *ClassicLru)SetOnEvicted(f func(interface{}, interface{})) {
cl.OnEvicted = f
}
func (cl *ClassicLru)Add(key, value interface{}) {
if cl.cache == nil {
cl.ll = list.New()
cl.cache = make(map[interface{}]*list.Element)
}
if ee, ok := cl.cache[key]; ok {
cl.ll.MoveToFront(ee)
ee.Value.(*lruEntry).Value = value
return
}
ee := cl.ll.PushFront(&lruEntry{value, key})
cl.cache[key] = ee
if cl.MaxLen != 0 && cl.MaxLen < cl.ll.Len() {
cl.RemoveOldest()
}
}
func (cl *ClassicLru)Get(key interface{}) (value interface{}, ok bool) {
if cl.cache == nil {
return
}
if ee, ok := cl.cache[key]; ok {
cl.ll.MoveToFront(ee)
return ee.Value.(*lruEntry).Value, true
}
return nil, false
}
func (cl *ClassicLru)RemoveOldest() {
if cl.cache == nil {
return
}
ee := cl.ll.Back()
le := ee.Value.(*lruEntry)
if ee != nil {
cl.ll.Remove(ee)
delete(cl.cache, le.Key)
if cl.OnEvicted != nil {
cl.OnEvicted(le.Key, le.Value)
}
}
}