...
1
16
17
18 package lru
19
20 import "container/list"
21
22
23 type Cache struct {
24
25
26 MaxEntries int
27
28
29
30 OnEvicted func(key Key, value interface{})
31
32 ll *list.List
33 cache map[interface{}]*list.Element
34 }
35
36
37 type Key interface{}
38
39 type entry struct {
40 key Key
41 value interface{}
42 }
43
44
45
46
47 func New(maxEntries int) *Cache {
48 return &Cache{
49 MaxEntries: maxEntries,
50 ll: list.New(),
51 cache: make(map[interface{}]*list.Element),
52 }
53 }
54
55
56 func (c *Cache) Add(key Key, value interface{}) {
57 if c.cache == nil {
58 c.cache = make(map[interface{}]*list.Element)
59 c.ll = list.New()
60 }
61 if ee, ok := c.cache[key]; ok {
62 c.ll.MoveToFront(ee)
63 ee.Value.(*entry).value = value
64 return
65 }
66 ele := c.ll.PushFront(&entry{key, value})
67 c.cache[key] = ele
68 if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {
69 c.RemoveOldest()
70 }
71 }
72
73
74 func (c *Cache) Get(key Key) (value interface{}, ok bool) {
75 if c.cache == nil {
76 return
77 }
78 if ele, hit := c.cache[key]; hit {
79 c.ll.MoveToFront(ele)
80 return ele.Value.(*entry).value, true
81 }
82 return
83 }
84
85
86 func (c *Cache) Remove(key Key) {
87 if c.cache == nil {
88 return
89 }
90 if ele, hit := c.cache[key]; hit {
91 c.removeElement(ele)
92 }
93 }
94
95
96 func (c *Cache) RemoveOldest() {
97 if c.cache == nil {
98 return
99 }
100 ele := c.ll.Back()
101 if ele != nil {
102 c.removeElement(ele)
103 }
104 }
105
106 func (c *Cache) removeElement(e *list.Element) {
107 c.ll.Remove(e)
108 kv := e.Value.(*entry)
109 delete(c.cache, kv.key)
110 if c.OnEvicted != nil {
111 c.OnEvicted(kv.key, kv.value)
112 }
113 }
114
115
116 func (c *Cache) Len() int {
117 if c.cache == nil {
118 return 0
119 }
120 return c.ll.Len()
121 }
122
123
124 func (c *Cache) Clear() {
125 if c.OnEvicted != nil {
126 for _, e := range c.cache {
127 kv := e.Value.(*entry)
128 c.OnEvicted(kv.key, kv.value)
129 }
130 }
131 c.ll = nil
132 c.cache = nil
133 }
134
View as plain text