You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
1.9 KiB

2 years ago
package fifo
import (
"cache"
"container/list"
)
/**
*
*/
type fifo struct {
// 缓存最大容量
maxBytes int
// 当一个 entry 从缓存中移除时调用该回调函数,默认为 nil
onEvicted func(key string, value any)
//已使用的字节数只包括值key 不算
usedBytes int
//缓存容器,存放entry
ll *list.List
//指针容器
cache map[string]*list.Element
}
func New(maxBytes int, onEvicted func(key string, value any)) cache.Cache {
return &fifo{
maxBytes: maxBytes,
onEvicted: onEvicted,
ll: list.New(),
cache: make(map[string]*list.Element),
}
}
// Set 往 Cache 尾部增加一个元素(如果已经存在,则放入尾部,并修改值)
func (f *fifo) Set(key string, value any) {
//元素存在
if e, ok := f.cache[key]; ok {
f.ll.MoveToBack(e)
en := e.Value.(*entry)
f.usedBytes = f.usedBytes - cache.CalcLen(en.value) + cache.CalcLen(value)
en.value = value
} else {
en := &entry{key, value}
e := f.ll.PushBack(en)
f.cache[key] = e
f.usedBytes += en.Len()
//元素容量校验
if f.CheckOverFlow() {
f.DelOldest()
}
}
}
// CheckOverFlow 校验容量是否溢出
func (f *fifo) CheckOverFlow() bool {
return f.maxBytes > 0 && f.usedBytes > f.maxBytes
}
func (f *fifo) Get(key string) any {
if e, ok := f.cache[key]; ok {
return e.Value.(*entry).value
}
return nil
}
func (f *fifo) Del(key string) {
if e, ok := f.cache[key]; ok {
f.removeElement(e)
}
}
func (f *fifo) DelOldest() {
//删除列表头部元素
f.removeElement(f.ll.Front())
}
func (f *fifo) Len() int {
return f.ll.Len()
}
// removeElement 删除元素
func (f *fifo) removeElement(e *list.Element) {
if e == nil {
return
}
f.ll.Remove(e)
en := e.Value.(*entry)
f.usedBytes -= en.Len()
delete(f.cache, en.key)
if f.onEvicted != nil {
f.onEvicted(en.key, en.value)
}
}
type entry struct {
key string
value any
}
func (e *entry) Len() int {
return cache.CalcLen(e.value)
}