2018-03-27 17:53:46 +08:00
|
|
|
|
// Copyright 2018 gf Author(https://gitee.com/johng/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://gitee.com/johng/gf.
|
|
|
|
|
|
|
|
|
|
|
|
package gcache
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"fmt"
|
2018-03-27 23:10:27 +08:00
|
|
|
|
"container/list"
|
2018-03-27 17:53:46 +08:00
|
|
|
|
"gitee.com/johng/gf/g/container/glist"
|
|
|
|
|
|
"gitee.com/johng/gf/g/container/gqueue"
|
|
|
|
|
|
"gitee.com/johng/gf/g/container/gmap"
|
2018-03-27 23:10:27 +08:00
|
|
|
|
|
2018-03-27 17:53:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// LRU算法实现对象,底层双向链表使用了标准库的list.List
|
2018-09-15 16:40:13 +08:00
|
|
|
|
type memCacheLru struct {
|
|
|
|
|
|
data *gmap.Map // 记录键名与链表中的位置项指针
|
|
|
|
|
|
list *glist.List // 键名历史记录链表
|
|
|
|
|
|
queue *gqueue.Queue // 事件队列
|
2018-03-27 17:53:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-15 16:40:13 +08:00
|
|
|
|
// 创建LRU管理对象
|
|
|
|
|
|
func newMemCacheLru() *memCacheLru {
|
|
|
|
|
|
lru := &memCacheLru {
|
2018-03-27 17:53:46 +08:00
|
|
|
|
list : glist.New(),
|
2018-09-15 16:40:13 +08:00
|
|
|
|
data : gmap.New(),
|
2018-03-27 17:53:46 +08:00
|
|
|
|
queue : gqueue.New(),
|
|
|
|
|
|
}
|
|
|
|
|
|
go lru.StartAutoLoop()
|
|
|
|
|
|
return lru
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 关闭LRU对象
|
2018-09-15 16:40:13 +08:00
|
|
|
|
func (lru *memCacheLru) Close() {
|
2018-03-27 17:53:46 +08:00
|
|
|
|
lru.queue.Close()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-27 23:10:27 +08:00
|
|
|
|
// 删除指定数据项
|
2018-09-15 16:40:13 +08:00
|
|
|
|
func (lru *memCacheLru) Remove(key interface{}) {
|
2018-03-27 23:10:27 +08:00
|
|
|
|
if v := lru.data.Get(key); v != nil {
|
2018-09-15 16:40:13 +08:00
|
|
|
|
lru.data.Remove(key)
|
2018-03-27 23:10:27 +08:00
|
|
|
|
lru.list.Remove(v.(*list.Element))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-19 09:47:50 +08:00
|
|
|
|
// 当前LRU数据大小
|
|
|
|
|
|
func (lru *memCacheLru) Size() int {
|
|
|
|
|
|
return lru.data.Size()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-27 17:53:46 +08:00
|
|
|
|
// 添加LRU数据项
|
2018-09-15 16:40:13 +08:00
|
|
|
|
func (lru *memCacheLru) Push(key interface{}) {
|
|
|
|
|
|
lru.queue.Push(key)
|
2018-03-27 17:53:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 从链表尾删除LRU数据项,并返回对应数据
|
2018-09-15 16:40:13 +08:00
|
|
|
|
func (lru *memCacheLru) Pop() interface{} {
|
2018-03-27 17:53:46 +08:00
|
|
|
|
if v := lru.list.PopBack(); v != nil {
|
2018-09-15 16:40:13 +08:00
|
|
|
|
lru.data.Remove(v)
|
|
|
|
|
|
return v
|
2018-03-27 17:53:46 +08:00
|
|
|
|
}
|
2018-09-15 16:40:13 +08:00
|
|
|
|
return nil
|
2018-03-27 17:53:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 从链表头打印LRU链表值
|
2018-09-15 16:40:13 +08:00
|
|
|
|
func (lru *memCacheLru) Print() {
|
2018-03-27 17:53:46 +08:00
|
|
|
|
for _, v := range lru.list.FrontAll() {
|
2018-09-15 16:40:13 +08:00
|
|
|
|
fmt.Printf("%v ", v)
|
2018-03-27 17:53:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-19 09:47:50 +08:00
|
|
|
|
// 异步执行协程,将queue中的数据同步到list中
|
2018-09-15 16:40:13 +08:00
|
|
|
|
func (lru *memCacheLru) StartAutoLoop() {
|
2018-03-27 17:53:46 +08:00
|
|
|
|
for {
|
2018-09-15 16:40:13 +08:00
|
|
|
|
if v := lru.queue.Pop(); v != nil {
|
2018-03-27 17:53:46 +08:00
|
|
|
|
// 删除对应链表项
|
2018-09-15 16:40:13 +08:00
|
|
|
|
if v := lru.data.Get(v); v != nil {
|
2018-03-27 17:53:46 +08:00
|
|
|
|
lru.list.Remove(v.(*list.Element))
|
|
|
|
|
|
}
|
2018-09-15 16:40:13 +08:00
|
|
|
|
// 将数据插入到链表头,并记录对应的链表项到哈希表中,便于检索
|
|
|
|
|
|
lru.data.Set(v, lru.list.PushFront(v))
|
2018-03-27 17:53:46 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|