mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
114 lines
2.3 KiB
Go
114 lines
2.3 KiB
Go
/*
|
|
LRU Cache package
|
|
|
|
Based off information obtained from:
|
|
|
|
https://girai.dev/blog/lru-cache-implementation-in-go/
|
|
https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)
|
|
*/
|
|
|
|
package cache
|
|
|
|
import "container/list"
|
|
|
|
// NewLRUCache returns a new non-concurrent-safe LRU cache with input capacity
|
|
func NewLRUCache(capacity uint64) *LRU {
|
|
return &LRU{
|
|
Cap: capacity,
|
|
l: list.New(),
|
|
items: make(map[any]*list.Element),
|
|
}
|
|
}
|
|
|
|
// Add adds a value to the cache
|
|
func (l *LRU) Add(key, value any) {
|
|
if f, o := l.items[key]; o {
|
|
l.l.MoveToFront(f)
|
|
if v, ok := f.Value.(*item); ok {
|
|
v.value = value
|
|
}
|
|
return
|
|
}
|
|
|
|
newItem := &item{key, value}
|
|
itemList := l.l.PushFront(newItem)
|
|
l.items[key] = itemList
|
|
if l.Len() > l.Cap {
|
|
l.removeOldestEntry()
|
|
}
|
|
}
|
|
|
|
// Get returns keys value from cache if found
|
|
func (l *LRU) Get(key any) any {
|
|
if i, f := l.items[key]; f {
|
|
l.l.MoveToFront(i)
|
|
if v, ok := i.Value.(*item); ok {
|
|
return v.value
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetOldest returns the oldest entry
|
|
func (l *LRU) getOldest() (key, value any) {
|
|
if x := l.l.Back(); x != nil {
|
|
if v, ok := x.Value.(*item); ok {
|
|
return v.key, v.value
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// GetNewest returns the newest entry
|
|
func (l *LRU) getNewest() (key, value any) {
|
|
if x := l.l.Front(); x != nil {
|
|
if v, ok := x.Value.(*item); ok {
|
|
return v.key, v.value
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// Contains check if key is in cache this does not update LRU
|
|
func (l *LRU) Contains(key any) (f bool) {
|
|
_, f = l.items[key]
|
|
return
|
|
}
|
|
|
|
// Remove removes key from the cache, if the key was removed.
|
|
func (l *LRU) Remove(key any) bool {
|
|
if i, f := l.items[key]; f {
|
|
l.removeElement(i)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Clear is used to completely clear the cache.
|
|
func (l *LRU) Clear() {
|
|
for x := range l.items {
|
|
delete(l.items, l.items[x])
|
|
}
|
|
l.l.Init()
|
|
}
|
|
|
|
// Len returns length of l
|
|
func (l *LRU) Len() uint64 {
|
|
return uint64(l.l.Len()) //nolint:gosec // False positive as uint64 (2^64-1) can support both 2^31-1 on 32bit systems and 2^63-1 on 64bit systems
|
|
}
|
|
|
|
// removeOldestEntry removes the oldest item from the cache.
|
|
func (l *LRU) removeOldestEntry() {
|
|
if i := l.l.Back(); i != nil {
|
|
l.removeElement(i)
|
|
}
|
|
}
|
|
|
|
// removeElement element from the cache
|
|
func (l *LRU) removeElement(e *list.Element) {
|
|
l.l.Remove(e)
|
|
if v, ok := e.Value.(*item); ok {
|
|
delete(l.items, v.key)
|
|
}
|
|
}
|