summaryrefslogtreecommitdiff
path: root/lib/caching/linkedlist.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/caching/linkedlist.go')
-rw-r--r--lib/caching/linkedlist.go74
1 files changed, 34 insertions, 40 deletions
diff --git a/lib/caching/linkedlist.go b/lib/caching/linkedlist.go
index a13a107..2fa5d03 100644
--- a/lib/caching/linkedlist.go
+++ b/lib/caching/linkedlist.go
@@ -10,14 +10,11 @@ import (
// LinkedListEntry [T] is an entry in a LinkedList [T].
type LinkedListEntry[T any] struct {
- list *LinkedList[T]
- older, newer *LinkedListEntry[T]
+ List *LinkedList[T]
+ Older, Newer *LinkedListEntry[T]
Value T
}
-func (entry *LinkedListEntry[T]) Older() *LinkedListEntry[T] { return entry.older }
-func (entry *LinkedListEntry[T]) Newer() *LinkedListEntry[T] { return entry.newer }
-
// LinkedList is a doubly-linked list.
//
// Rather than "head/tail", "front/back", or "next/prev", it has
@@ -32,12 +29,13 @@ func (entry *LinkedListEntry[T]) Newer() *LinkedListEntry[T] { return entry.newe
// disadvantages that it has fewer safety checks and fewer features in
// general.
type LinkedList[T any] struct {
- oldest, newest *LinkedListEntry[T]
+ Len int
+ Oldest, Newest *LinkedListEntry[T]
}
// IsEmpty returns whether the list empty or not.
func (l *LinkedList[T]) IsEmpty() bool {
- return l.oldest == nil
+ return l.Oldest == nil
}
// Delete removes an entry from the list. The entry is invalid once
@@ -49,24 +47,25 @@ func (l *LinkedList[T]) IsEmpty() bool {
// It is invalid (runtime-panic) to call Delete on an entry that
// isn't in the list.
func (l *LinkedList[T]) Delete(entry *LinkedListEntry[T]) {
- if entry.list != l {
+ if entry.List != l {
panic(fmt.Errorf("LinkedList.Delete: entry %p not in list", entry))
}
- if entry.newer == nil {
- l.newest = entry.older
+ l.Len--
+ if entry.Newer == nil {
+ l.Newest = entry.Older
} else {
- entry.newer.older = entry.older
+ entry.Newer.Older = entry.Older
}
- if entry.older == nil {
- l.oldest = entry.newer
+ if entry.Older == nil {
+ l.Oldest = entry.Newer
} else {
- entry.older.newer = entry.newer
+ entry.Older.Newer = entry.Newer
}
// no memory leaks
- entry.list = nil
- entry.older = nil
- entry.newer = nil
+ entry.List = nil
+ entry.Older = nil
+ entry.Newer = nil
}
// Store appends a value to the "newest" end of the list, returning
@@ -77,16 +76,17 @@ func (l *LinkedList[T]) Delete(entry *LinkedListEntry[T]) {
// It is invalid (runtime-panic) to call Store on an entry that is
// already in a list.
func (l *LinkedList[T]) Store(entry *LinkedListEntry[T]) {
- if entry.list != nil {
+ if entry.List != nil {
panic(fmt.Errorf("LinkedList.Store: entry %p is already in a list", entry))
}
- entry.list = l
- entry.older = l.newest
- l.newest = entry
- if entry.older == nil {
- l.oldest = entry
+ l.Len++
+ entry.List = l
+ entry.Older = l.Newest
+ l.Newest = entry
+ if entry.Older == nil {
+ l.Oldest = entry
} else {
- entry.older.newer = entry
+ entry.Older.Newer = entry
}
}
@@ -99,29 +99,23 @@ func (l *LinkedList[T]) Store(entry *LinkedListEntry[T]) {
// It is invalid (runtime-panic) to call MoveToNewest on an entry that
// isn't in the list.
func (l *LinkedList[T]) MoveToNewest(entry *LinkedListEntry[T]) {
- if entry.list != l {
+ if entry.List != l {
panic(fmt.Errorf("LinkedList.MoveToNewest: entry %p not in list", entry))
}
- if entry.newer == nil {
+ if entry.Newer == nil {
// Already newest.
return
}
- entry.newer.older = entry.older
- if entry.older == nil {
- l.oldest = entry.newer
+ entry.Newer.Older = entry.Older
+ if entry.Older == nil {
+ l.Oldest = entry.Newer
} else {
- entry.older.newer = entry.newer
+ entry.Older.Newer = entry.Newer
}
- entry.older = l.newest
- l.newest.newer = entry
-
- entry.newer = nil
- l.newest = entry
-}
+ entry.Older = l.Newest
+ l.Newest.Newer = entry
-// Oldest returns the entry at the "oldest" end of the list, or nil if
-// the list is empty.
-func (l *LinkedList[T]) Oldest() *LinkedListEntry[T] {
- return l.oldest
+ entry.Newer = nil
+ l.Newest = entry
}