-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathlru_cache.go
129 lines (112 loc) · 2.58 KB
/
lru_cache.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package turbo
import (
"context"
"sync/atomic"
"time"
)
type Entry struct {
Timerid uint32
Value interface{}
}
//lru的cache
type LRUCache struct {
ctx context.Context
hit uint64
total uint64
cache *cache
tw *TimerWheel
}
//LRU的cache
func NewLRUCache(
ctx context.Context,
maxcapacity int,
expiredTw *TimerWheel,
OnEvicted func(k, v interface{})) *LRUCache {
cache := New(maxcapacity)
cache.OnEvicted = func(key Key, value interface{}) {
vv := value.(Entry)
if nil != OnEvicted {
OnEvicted(key.(interface{}), vv.Value)
}
//因为已经淘汰,所以清理掉定时过期的任务
expiredTw.CancelTimer(vv.Timerid)
}
lru := &LRUCache{
ctx: ctx,
cache: cache,
tw: expiredTw}
return lru
}
//本时间段的命中率
func (self *LRUCache) HitRate() (int, int) {
currHit := self.hit
currTotal := self.total
if currTotal <= 0 {
return 0, self.Length()
}
return int(currHit * 100 / currTotal), self.Length()
}
//获取
func (self *LRUCache) Get(key interface{}) (interface{}, bool) {
atomic.AddUint64(&self.total, 1)
if v, ok := self.cache.Get(key); ok {
atomic.AddUint64(&self.hit, 1)
return v.(Entry).Value, true
}
return nil, false
}
//增加元素
func (self *LRUCache) Put(key, v interface{}, ttl time.Duration) chan time.Time {
entry := Entry{Value: v}
var ttlChan chan time.Time
if ttl > 0 {
//超时过期或者取消的时候也删除
if nil != self.tw {
//如果数据存在,则更新过期时间
if v, ok := self.cache.Get(key); ok {
if exist, ok := v.(Entry); ok {
//先取消掉过期淘汰定时,然后再重新设置定时器
self.tw.CancelTimer(exist.Timerid)
}
}
timerid, ch := self.tw.AddTimer(ttl, func(tid uint32, t time.Time) {
//直接移除就可以,cache淘汰会调用OnEvicted
self.cache.Remove(key)
}, func(tid uint32, t time.Time) {
})
entry.Timerid = timerid
ttlChan = ch
}
}
self.cache.Add(key, entry)
return ttlChan
}
//移除元素
func (self *LRUCache) Remove(key interface{}) interface{} {
entry := self.cache.Remove(key)
if nil != entry {
e := entry.(Entry)
if nil != self.tw {
self.tw.CancelTimer(e.Timerid)
}
return e.Value
}
return nil
}
//是否包含当前的KEY
func (self *LRUCache) Contains(key interface{}) bool {
if _, ok := self.cache.Get(key); ok {
return ok
}
return false
}
//c length
func (self *LRUCache) Length() int {
return self.cache.Len()
}
func (self *LRUCache) Iterator(do func(k, v interface{}) error) {
self.cache.Iterator(func(k, v interface{}) error {
entry := v.(Entry)
return do(k, entry.Value)
})
}