github.com/avicd/go-utilx@v0.1.0/bufx/lru.go (about) 1 package bufx 2 3 import ( 4 "github.com/avicd/go-utilx/datax" 5 "sync" 6 ) 7 8 type LruCache[K comparable, V any] struct { 9 Size int 10 store map[K]*datax.LinkedNode[Entry[K, V]] 11 first *datax.LinkedNode[Entry[K, V]] 12 last *datax.LinkedNode[Entry[K, V]] 13 mutex sync.RWMutex 14 firstLocker sync.Mutex 15 } 16 17 func (it *LruCache[K, V]) Get(key K) (V, bool) { 18 var ret V 19 var exist bool 20 it.mutex.RLock() 21 if node, ok := it.store[key]; ok { 22 it.asFirst(node) 23 ret = node.Item.Value 24 exist = true 25 } 26 it.mutex.RUnlock() 27 return ret, exist 28 } 29 30 func (it *LruCache[K, V]) asFirst(node *datax.LinkedNode[Entry[K, V]]) { 31 it.firstLocker.Lock() 32 if it.first != node { 33 if it.first == nil { 34 node.Remove() 35 it.first = node 36 it.last = node 37 } else { 38 if it.last == node { 39 it.last = node.Pre 40 } 41 node.Remove() 42 it.first.Insert(node) 43 it.first = node 44 } 45 } 46 it.firstLocker.Unlock() 47 } 48 49 func (it *LruCache[K, V]) removeLast() { 50 if it.last != nil { 51 delete(it.store, it.last.Item.Key) 52 if it.last.Pre != nil { 53 it.last = it.last.Pre 54 it.last.Next = nil 55 } else { 56 it.last = nil 57 } 58 } 59 } 60 61 func (it *LruCache[K, V]) Put(key K, val V) { 62 it.mutex.Lock() 63 node := it.store[key] 64 if node == nil { 65 if it.Size > 0 && len(it.store)+1 > it.Size { 66 it.removeLast() 67 } 68 node = &datax.LinkedNode[Entry[K, V]]{} 69 } 70 if it.store == nil { 71 it.store = map[K]*datax.LinkedNode[Entry[K, V]]{} 72 } 73 node.Item = Entry[K, V]{Key: key, Value: val} 74 it.store[key] = node 75 it.asFirst(node) 76 it.mutex.Unlock() 77 } 78 79 func (it *LruCache[K, V]) Remove(key K) bool { 80 it.mutex.Lock() 81 if node, ok := it.store[key]; ok { 82 delete(it.store, node.Item.Key) 83 if it.first == node { 84 it.first = node.Next 85 } 86 if it.last == node { 87 it.last = node.Pre 88 } 89 node.Remove() 90 } 91 it.mutex.Unlock() 92 return false 93 } 94 95 func (it *LruCache[K, V]) Len() int { 96 return len(it.store) 97 } 98 99 func (it *LruCache[K, V]) Clear() { 100 it.mutex.Lock() 101 it.store = map[K]*datax.LinkedNode[Entry[K, V]]{} 102 it.first = nil 103 it.last = nil 104 it.mutex.Unlock() 105 }