Files
gocryptotrader/common/cache/lru.go
Andrew e5b64a5580 (COMMON): Basic (Least Recently Used) LRU caching system (#420)
* started adding basic lru cache system

* Added basic LRU cache including Add Get Remove Contains ContainsOrAdd Clear

* wording changes on comments

* removed exported var's in strut as they are not required

* Added README

* README updates

* rm line :D

* swapped to mutex over rwmutex updated comments

* unexported getNewest & getOldest

* unexported getNewest & getOldest

* Updated comments and cited references in source

* updated comments
2020-01-24 13:59:33 +11:00

107 lines
2.2 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[interface{}]*list.Element),
}
}
// Add adds a value to the cache
func (l *LRU) Add(key, value interface{}) {
if f, o := l.items[key]; o {
l.l.MoveToFront(f)
f.Value.(*item).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 interface{}) interface{} {
if i, f := l.items[key]; f {
l.l.MoveToFront(i)
return i.Value.(*item).value
}
return nil
}
// GetOldest returns the oldest entry
func (l *LRU) getOldest() (key, value interface{}) {
x := l.l.Back()
if x != nil {
return x.Value.(*item).key, x.Value.(*item).value
}
return
}
// GetNewest returns the newest entry
func (l *LRU) getNewest() (key, value interface{}) {
x := l.l.Front()
if x != nil {
return x.Value.(*item).key, x.Value.(*item).value
}
return
}
// Contains check if key is in cache this does not update LRU
func (l *LRU) Contains(key interface{}) (f bool) {
_, f = l.items[key]
return
}
// Remove removes key from the cache, if the key was removed.
func (l *LRU) Remove(key interface{}) 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())
}
// removeOldest removes the oldest item from the cache.
func (l *LRU) removeOldestEntry() {
i := l.l.Back()
if i != nil {
l.removeElement(i)
}
}
// removeElement element from the cache
func (l *LRU) removeElement(e *list.Element) {
l.l.Remove(e)
delete(l.items, e.Value.(*item).key)
}