diff --git a/internal/list/entry.go b/internal/list/entry.go index c03cfee..8d1f5fc 100644 --- a/internal/list/entry.go +++ b/internal/list/entry.go @@ -19,8 +19,18 @@ type Entry[K comparable, V any] struct { } // PrevEntry returns the previous list element or nil. +// note: can't get root entry func (e *Entry[K, V]) PrevEntry() *Entry[K, V] { - if p := e.prev; e.list != nil && p != e.list.Root() { + if p := e.prev; e.list != nil && p != &e.list.root { + return p + } + return nil +} + +// NextEntry returns the next list element or nil. +// note: can't get root entry +func (e *Entry[K, V]) NextEntry() *Entry[K, V] { + if p := e.next; e.list != nil && p != &e.list.root { return p } return nil diff --git a/internal/list/list.go b/internal/list/list.go index f2b1bca..00255b3 100644 --- a/internal/list/list.go +++ b/internal/list/list.go @@ -121,20 +121,15 @@ func (l *DoublyLinkedList[K, V]) Back() *Entry[K, V] { return l.root.prev } -// Root returns the root of the list. -func (l *DoublyLinkedList[K, V]) Root() *Entry[K, V] { - return &l.root -} - // Root returns the root of the list. func (l *DoublyLinkedList[K, V]) Debug() []string { asc := []string{"root"} - for ent := l.Root().next; ent.list == l; ent = ent.next { + for ent := l.root.next; ent.list == l; ent = ent.next { asc = append(asc, fmt.Sprintf("%v", ent.Key)) } asc = append(asc, "root") desc := []string{"root"} - for ent := l.Root().prev; ent.list == l; ent = ent.prev { + for ent := l.root.prev; ent.list == l; ent = ent.prev { desc = append(desc, fmt.Sprintf("%v", ent.Key)) } desc = append(desc, "root") diff --git a/internal/list/list_test.go b/internal/list/list_test.go index 1766954..1ed70c5 100644 --- a/internal/list/list_test.go +++ b/internal/list/list_test.go @@ -37,7 +37,7 @@ func TestLruList_PushFront(t *testing.T) { assert.EqualValues(t, 1, l.Len()) second := l.PushFront(2, 22) - assert.EqualValues(t, second.prev, l.Root()) // forbid root + assert.EqualValues(t, second.prev, &l.root) // forbid root assert.Equal(t, first.PrevEntry(), second) assert.EqualValues(t, 2, second.Key) @@ -118,7 +118,7 @@ func TestLruList_PushBack(t *testing.T) { assert.EqualValues(t, 1, l.Len()) second := l.PushBack(2, 22) - assert.Equal(t, second.next, l.Root()) + assert.Equal(t, second.next, &l.root) assert.Equal(t, first.next, second) assert.EqualValues(t, 2, second.Key) @@ -155,5 +155,7 @@ func TestLruList_Entry(t *testing.T) { first := l.PushFront(1, 1) second := l.PushFront(2, 2) assert.Equal(t, first.PrevEntry(), second) + assert.Equal(t, second.NextEntry(), first) assert.Nil(t, second.PrevEntry()) + assert.Nil(t, first.NextEntry()) } diff --git a/simplelfu/lfu.go b/simplelfu/lfu.go index 2484342..318f9f0 100644 --- a/simplelfu/lfu.go +++ b/simplelfu/lfu.go @@ -190,12 +190,13 @@ func (c *Cache[K, V]) removeElement(ent *list.Entry[K, *LFUValue[V]]) { // moveForward is used to move a given list element to the front of the cache func (c *Cache[K, V]) moveForward(ent *list.Entry[K, *LFUValue[V]]) { + // if ent is root entry, ent.PrevEntry() is nil for prev := ent.PrevEntry(); prev != nil; prev = ent.PrevEntry() { if ent.Value.GetVisit() < prev.Value.GetVisit() { break } - if !c.evictList.MoveToAt(ent, prev.PrevEntry()) { - break - } + // because ent can't get root entry from PrevEntry(), + // so we don't need to check + _ = c.evictList.MoveToAt(ent, prev.PrevEntry()) } }