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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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)
}