prysm-pulse/container/doubly-linked-list/list.go
Potuz cc454bb42c
Cycle the BLS changes pool when falling below a threshold (#11873)
* Cycle the BLS changes pool when falling below a threshold

* move cycle logic within pool

* set threshold at 2000

* fix conflict

* more fixes

---------

Co-authored-by: kasey <489222+kasey@users.noreply.github.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-28 14:42:03 +00:00

138 lines
2.7 KiB
Go

package doublylinkedlist
import "github.com/pkg/errors"
var (
errNextOnNil = errors.New("cannot get next node of nil node")
errPrevOnNil = errors.New("cannot get previous node of nil node")
errValueOnNil = errors.New("cannot get value of nil node")
)
// List is a generic doubly-linked list whose nodes can store any data type.
// It allows retrieving pointers to the first and last nodes.
type List[T any] struct {
first *Node[T]
last *Node[T]
len int
}
// Node is a generic data structure that contains three fields:
// references to the previous and to the next node in the list, and one data field.
type Node[T any] struct {
value T
prev *Node[T]
next *Node[T]
}
// Copy returns a copy of the origina list.
func (l *List[T]) Copy() *List[T] {
if l == nil {
return nil
}
list := &List[T]{}
if l.len == 0 {
return list
}
for n := l.First(); n != nil; n = n.next {
list.Append(n.Copy())
}
return list
}
// First gets the reference to the first node in the list.
func (l *List[T]) First() *Node[T] {
return l.first
}
// Last gets the reference to the last node in the list.
func (l *List[T]) Last() *Node[T] {
return l.last
}
// Len gets the length of the list.
func (l *List[T]) Len() int {
return l.len
}
// Append adds the passed in node to the end of the list.
func (l *List[T]) Append(n *Node[T]) {
if l.first == nil {
l.first = n
} else {
n.prev = l.last
l.last.next = n
}
l.last = n
l.len++
}
// Remove removes the passed in node from the list.
func (l *List[T]) Remove(n *Node[T]) {
if n == nil {
return
}
if n == l.First() {
if n == l.last {
l.first = nil
l.last = nil
} else {
n.next.prev = nil
l.first = n.next
}
} else {
if n == l.last {
n.prev.next = nil
l.last = n.prev
} else {
if n.next == nil || n.prev == nil {
// The node is not in the list,
// otherwise it would be in the middle of two nodes.
return
}
n.prev.next = n.next
n.next.prev = n.prev
}
}
n = nil
l.len--
}
// NewNode creates a new node with the passed in value.
func NewNode[T any](value T) *Node[T] {
return &Node[T]{value: value}
}
// Next gets the node's successor node.
func (n *Node[T]) Next() (*Node[T], error) {
if n == nil {
return nil, errNextOnNil
}
return n.next, nil
}
// Prev gets the node's predecessor node.
func (n *Node[T]) Prev() (*Node[T], error) {
if n == nil {
return nil, errPrevOnNil
}
return n.prev, nil
}
// Value gets the value stored in the node.
func (n *Node[T]) Value() (T, error) {
if n == nil {
return *new(T), errValueOnNil
}
return n.value, nil
}
// Copy copies the given node and returns a new one. It does not do a deep copy
// of T.
func (n *Node[T]) Copy() *Node[T] {
if n == nil {
return nil
}
return NewNode(n.value)
}