gf/g/os/gcache/gcache_mem_cache_lru.go

105 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gcache
import (
"fmt"
"github.com/gogf/gf/g/container/glist"
"github.com/gogf/gf/g/container/gmap"
"github.com/gogf/gf/g/container/gtype"
"github.com/gogf/gf/g/os/gtimer"
"time"
)
// LRU算法实现对象底层双向链表使用了标准库的list.List
type memCacheLru struct {
cache *memCache // 所属Cache对象
data *gmap.Map // 记录键名与链表中的位置项指针
list *glist.List // 键名历史记录链表
rawList *glist.List // 事件列表
closed *gtype.Bool // 是否关闭
}
// 创建LRU管理对象
func newMemCacheLru(cache *memCache) *memCacheLru {
lru := &memCacheLru {
cache : cache,
data : gmap.New(),
list : glist.New(),
rawList : glist.New(),
closed : gtype.NewBool(),
}
gtimer.AddSingleton(time.Second, lru.SyncAndClear)
return lru
}
// 关闭LRU对象
func (lru *memCacheLru) Close() {
lru.closed.Set(true)
}
// 删除指定数据项
func (lru *memCacheLru) Remove(key interface{}) {
if v := lru.data.Get(key); v != nil {
lru.data.Remove(key)
lru.list.Remove(v.(*glist.Element))
}
}
// 当前LRU数据大小
func (lru *memCacheLru) Size() int {
return lru.data.Size()
}
// 添加LRU数据项
func (lru *memCacheLru) Push(key interface{}) {
lru.rawList.PushBack(key)
}
// 从链表尾删除LRU数据项并返回对应数据
func (lru *memCacheLru) Pop() interface{} {
if v := lru.list.PopBack(); v != nil {
lru.data.Remove(v)
return v
}
return nil
}
// 从链表头打印LRU链表值
func (lru *memCacheLru) Print() {
for _, v := range lru.list.FrontAll() {
fmt.Printf("%v ", v)
}
fmt.Println()
}
// 异步执行协程将queue中的数据同步到list中
func (lru *memCacheLru) SyncAndClear() {
if lru.closed.Val() {
gtimer.Exit()
return
}
// 数据同步
for {
if v := lru.rawList.PopFront(); v != nil {
// 删除对应链表项
if v := lru.data.Get(v); v != nil {
lru.list.Remove(v.(*glist.Element))
}
// 将数据插入到链表头,并记录对应的链表项到哈希表中,便于检索
lru.data.Set(v, lru.list.PushFront(v))
} else {
break
}
}
// 数据清理
for i := lru.Size() - lru.cache.cap; i > 0; i-- {
if s := lru.Pop(); s != nil {
lru.cache.clearByKey(s, true)
}
}
}