You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			89 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
			
		
		
	
	
			89 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
| package lru
 | |
| 
 | |
| import (
 | |
| 	"container/list"
 | |
| 	"sync"
 | |
| )
 | |
| 
 | |
| type node struct {
 | |
| 	k interface{}
 | |
| 	v interface{}
 | |
| }
 | |
| 
 | |
| type LRU struct {
 | |
| 	mutex   sync.RWMutex
 | |
| 	maxLen  int // if maxLen<=0 then no limit
 | |
| 	lruList *list.List
 | |
| 	datas   map[interface{}]*list.Element
 | |
| }
 | |
| 
 | |
| func New(maxLen int) *LRU {
 | |
| 	return &LRU{
 | |
| 		maxLen:  maxLen,
 | |
| 		lruList: list.New(),
 | |
| 		datas:   make(map[interface{}]*list.Element),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (lc *LRU) PushFront(k, v interface{}) {
 | |
| 	lc.mutex.Lock()
 | |
| 	defer lc.mutex.Unlock()
 | |
| 
 | |
| 	if e, ok := lc.datas[k]; ok {
 | |
| 		e.Value.(*node).v = v
 | |
| 		lc.lruList.MoveToFront(e)
 | |
| 	} else {
 | |
| 		e := lc.lruList.PushFront(&node{k, v})
 | |
| 		lc.datas[k] = e
 | |
| 	}
 | |
| 	if lc.maxLen > 0 && lc.lruList.Len() > lc.maxLen {
 | |
| 		lc.popTail()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (lc *LRU) PopTail() (interface{}, bool) {
 | |
| 	lc.mutex.Lock()
 | |
| 	defer lc.mutex.Unlock()
 | |
| 
 | |
| 	return lc.popTail()
 | |
| }
 | |
| 
 | |
| func (lc *LRU) Get(k interface{}) (interface{}, bool) {
 | |
| 	lc.mutex.Lock()
 | |
| 	defer lc.mutex.Unlock()
 | |
| 
 | |
| 	if e, ok := lc.datas[k]; ok {
 | |
| 		lc.lruList.MoveToFront(e)
 | |
| 		return e.Value.(*node).v, ok
 | |
| 	}
 | |
| 	return nil, false
 | |
| }
 | |
| 
 | |
| func (lc *LRU) Del(k interface{}) {
 | |
| 	lc.mutex.Lock()
 | |
| 	defer lc.mutex.Unlock()
 | |
| 	lc.del(k)
 | |
| }
 | |
| 
 | |
| func (lc *LRU) Len() int {
 | |
| 	lc.mutex.RLock()
 | |
| 	defer lc.mutex.RUnlock()
 | |
| 	return lc.lruList.Len()
 | |
| }
 | |
| 
 | |
| func (lc *LRU) popTail() (interface{}, bool) {
 | |
| 	e := lc.lruList.Back()
 | |
| 	if e != nil {
 | |
| 		lc.del(e.Value.(*node).k)
 | |
| 		return e.Value.(*node).v, true
 | |
| 	}
 | |
| 	return nil, false
 | |
| }
 | |
| 
 | |
| func (lc *LRU) del(k interface{}) {
 | |
| 	if e, ok := lc.datas[k]; ok {
 | |
| 		delete(lc.datas, k)
 | |
| 		lc.lruList.Remove(e)
 | |
| 	}
 | |
| }
 |