summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-list/list.go
diff options
context:
space:
mode:
authorLibravatar kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>2024-04-26 13:50:46 +0100
committerLibravatar GitHub <noreply@github.com>2024-04-26 13:50:46 +0100
commitc9c0773f2c2363dcfa37e675b83ec3f0b49bd0d9 (patch)
treedbd3409070765d5ca81448a574ccd32b4da1ffe6 /vendor/codeberg.org/gruf/go-list/list.go
parent[chore] update Docker container to use new go swagger hash (#2872) (diff)
downloadgotosocial-c9c0773f2c2363dcfa37e675b83ec3f0b49bd0d9.tar.xz
[performance] update remaining worker pools to use queues (#2865)
* start replacing client + federator + media workers with new worker + queue types * refactor federatingDB.Delete(), drop queued messages when deleting account / status * move all queue purging to the processor workers * undo toolchain updates * code comments, ensure dereferencer worker pool gets started * update gruf libraries in readme * start the job scheduler separately to the worker pools * reshuffle ordering or server.go + remove duplicate worker start / stop * update go-list version * fix vendoring * move queue invalidation to before wipeing / deletion, to ensure queued work not dropped * add logging to worker processing functions in testrig, don't start workers in unexpected places * update go-structr to add (+then rely on) QueueCtx{} type * ensure more worker pools get started properly in tests * fix remaining broken tests relying on worker queue logic * fix account test suite queue popping logic, ensure noop workers do not pull from queue * move back accidentally shuffled account deletion order * ensure error (non nil!!) gets passed in refactored federatingDB{}.Delete() * silently drop deletes from accounts not permitted to * don't warn log on forwarded deletes * make if else clauses easier to parse * use getFederatorMsg() * improved code comment * improved code comment re: requesting account delete checks * remove boolean result from worker start / stop since false = already running or already stopped * remove optional passed-in http.client * remove worker starting from the admin CLI commands (we don't need to handle side-effects) * update prune cli to start scheduler but not all of the workers * fix rebase issues * remove redundant return statements * i'm sorry sir linter
Diffstat (limited to 'vendor/codeberg.org/gruf/go-list/list.go')
-rw-r--r--vendor/codeberg.org/gruf/go-list/list.go204
1 files changed, 204 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-list/list.go b/vendor/codeberg.org/gruf/go-list/list.go
new file mode 100644
index 000000000..5490fa636
--- /dev/null
+++ b/vendor/codeberg.org/gruf/go-list/list.go
@@ -0,0 +1,204 @@
+package list
+
+// Elem represents an element in a doubly-linked list.
+type Elem[T any] struct {
+ Next *Elem[T]
+ Prev *Elem[T]
+ Value T
+}
+
+// List implements a doubly-linked list, where:
+// - Head = index 0 (i.e. the front)
+// - Tail = index n-1 (i.e. the back)
+type List[T any] struct {
+ Head *Elem[T]
+ Tail *Elem[T]
+ len int
+}
+
+// Len returns the current list length.
+func (l *List[T]) Len() int {
+ return l.len
+}
+
+// PushFront adds 'v' to the beginning of the list.
+func (l *List[T]) PushFront(v T) *Elem[T] {
+ elem := &Elem[T]{Value: v}
+ l.PushElemFront(elem)
+ return elem
+}
+
+// PushBack adds 'v' to the end of the list.
+func (l *List[T]) PushBack(v T) *Elem[T] {
+ elem := &Elem[T]{Value: v}
+ l.PushElemBack(elem)
+ return elem
+}
+
+// InsertBefore adds 'v' into the list before 'at'.
+func (l *List[T]) InsertBefore(v T, at *Elem[T]) *Elem[T] {
+ elem := &Elem[T]{Value: v}
+ l.InsertElemBefore(elem, at)
+ return elem
+}
+
+// InsertAfter adds 'v' into the list after 'at'.
+func (l *List[T]) InsertAfter(v T, at *Elem[T]) *Elem[T] {
+ elem := &Elem[T]{Value: v}
+ l.InsertElemAfter(elem, at)
+ return elem
+}
+
+// PushFrontNode adds 'elem' to the front of the list.
+func (l *List[T]) PushElemFront(elem *Elem[T]) {
+ if elem == l.Head {
+ return
+ }
+
+ // Set new head.
+ oldHead := l.Head
+ l.Head = elem
+
+ if oldHead != nil {
+ // Link to old head
+ elem.Next = oldHead
+ oldHead.Prev = elem
+ } else {
+ // First in list.
+ l.Tail = elem
+ }
+
+ // Incr count
+ l.len++
+}
+
+// PushBackNode adds 'elem' to the back of the list.
+func (l *List[T]) PushElemBack(elem *Elem[T]) {
+ if elem == l.Tail {
+ return
+ }
+
+ // Set new tail.
+ oldTail := l.Tail
+ l.Tail = elem
+
+ if oldTail != nil {
+ // Link to old tail
+ elem.Prev = oldTail
+ oldTail.Next = elem
+ } else {
+ // First in list.
+ l.Head = elem
+ }
+
+ // Incr count
+ l.len++
+}
+
+// InsertElemAfter adds 'elem' into the list after 'at' (i.e. at.Next = elem).
+func (l *List[T]) InsertElemAfter(elem *Elem[T], at *Elem[T]) {
+ if elem == at {
+ return
+ }
+
+ // Set new 'next'.
+ oldNext := at.Next
+ at.Next = elem
+
+ // Link to 'at'.
+ elem.Prev = at
+
+ if oldNext == nil {
+ // Set new tail
+ l.Tail = elem
+ } else {
+ // Link to 'prev'.
+ oldNext.Prev = elem
+ elem.Next = oldNext
+ }
+
+ // Incr count
+ l.len++
+}
+
+// InsertElemBefore adds 'elem' into the list before 'at' (i.e. at.Prev = elem).
+func (l *List[T]) InsertElemBefore(elem *Elem[T], at *Elem[T]) {
+ if elem == at {
+ return
+ }
+
+ // Set new 'prev'.
+ oldPrev := at.Prev
+ at.Prev = elem
+
+ // Link to 'at'.
+ elem.Next = at
+
+ if oldPrev == nil {
+ // Set new head
+ l.Head = elem
+ } else {
+ // Link to 'next'.
+ oldPrev.Next = elem
+ elem.Prev = oldPrev
+ }
+
+ // Incr count
+ l.len++
+}
+
+// Remove removes the 'elem' from the list.
+func (l *List[T]) Remove(elem *Elem[T]) {
+ // Get linked elems.
+ next := elem.Next
+ prev := elem.Prev
+
+ // Unset elem.
+ elem.Next = nil
+ elem.Prev = nil
+
+ switch {
+ // elem is ONLY one in list.
+ case next == nil && prev == nil:
+ l.Head = nil
+ l.Tail = nil
+
+ // elem is front in list.
+ case next != nil && prev == nil:
+ l.Head = next
+ next.Prev = nil
+
+ // elem is last in list.
+ case prev != nil && next == nil:
+ l.Tail = prev
+ prev.Next = nil
+
+ // elem in middle of list.
+ default:
+ next.Prev = prev
+ prev.Next = next
+ }
+
+ // Decr count
+ l.len--
+}
+
+// Range calls 'fn' on every element from head forward in list.
+func (l *List[T]) Range(fn func(*Elem[T])) {
+ if fn == nil {
+ panic("nil function")
+ }
+ for elem := l.Head; elem != nil; elem = elem.Next {
+ fn(elem)
+ }
+}
+
+// RangeReverse calls 'fn' on every element from tail backward in list.
+func (l *List[T]) RangeReverse(fn func(*Elem[T])) {
+ if fn == nil {
+ panic("nil function")
+ }
+ for elem := l.Tail; elem != nil; elem = elem.Prev {
+ fn(elem)
+ }
+}