Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add GetNewest() to get head entry from lru list #139

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lru.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ func (c *Cache[K, V]) GetOldest() (key K, value V, ok bool) {
return
}

// GetNewest returns the oldest entry
func (c *Cache[K, V]) GetNewest() (key K, value V, ok bool) {
c.lock.RLock()
key, value, ok = c.lru.GetNewest()
c.lock.RUnlock()
return
}

// Keys returns a slice of the keys in the cache, from oldest to newest.
func (c *Cache[K, V]) Keys() []K {
c.lock.RLock()
Expand Down
8 changes: 8 additions & 0 deletions simplelru/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ func (l *lruList[K, V]) back() *entry[K, V] {
return l.root.prev
}

// head returns the first element of list l or nil if the list is empty.
func (l *lruList[K, V]) head() *entry[K, V] {
if l.len == 0 {
return nil
}
return l.root.next
}

// lazyInit lazily initializes a zero List value.
func (l *lruList[K, V]) lazyInit() {
if l.root.next == nil {
Expand Down
8 changes: 8 additions & 0 deletions simplelru/lru.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) {
return
}

// GetNewest returns the newest entry
func (c *LRU[K, V]) GetNewest() (key K, value V, ok bool) {
if ent := c.evictList.head(); ent != nil {
return ent.key, ent.value, true
}
return
}

// Keys returns a slice of the keys in the cache, from oldest to newest.
func (c *LRU[K, V]) Keys() []K {
keys := make([]K, c.evictList.length())
Expand Down
3 changes: 3 additions & 0 deletions simplelru/lru_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ type LRUCache[K comparable, V any] interface {
// Returns the oldest entry from the cache. #key, value, isFound
GetOldest() (K, V, bool)

// Returns the newest entry from the cache. #key, value, isFound
GetNewest() (K, V, bool)

// Returns a slice of the keys in the cache, from oldest to newest.
Keys() []K

Expand Down
38 changes: 38 additions & 0 deletions simplelru/lru_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,44 @@ func TestLRU_GetOldest_RemoveOldest(t *testing.T) {
}
}

func TestLRU_GetNewest(t *testing.T) {
l, err := NewLRU[int, int](128, nil)
if err != nil {
t.Fatalf("err: %v", err)
}
for i := 0; i < 256; i++ {
l.Add(i, i)
}

k, _, ok := l.GetOldest()
if !ok {
t.Fatalf("missing")
}
if k != 128 {
t.Fatalf("bad oldest: %v", k)
}

k, _, ok = l.GetNewest()
if !ok {
t.Fatalf("missing")
}
if k != 255 {
t.Fatalf("bad newest: %v", k)
}

l.Get(128)
k, _, _ = l.GetNewest()
if k != 128 {
t.Fatalf("bad newest: %v", k)
}

l.Get(200)
k, _, _ = l.GetNewest()
if k != 200 {
t.Fatalf("bad newest: %v", k)
}
}

// Test that Add returns true/false if an eviction occurred
func TestLRU_Add(t *testing.T) {
evictCounter := 0
Expand Down