github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/internal/utils/linkedlist/linkedlist.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package list implements a doubly linked list. 6 // 7 // To iterate over a list (where l is a *List[T]): 8 // 9 // for e := l.Front(); e != nil; e = e.Next() { 10 // // do something with e.Value 11 // } 12 package list 13 14 import "sync" 15 16 func NewPool[T any]() *sync.Pool { 17 return &sync.Pool{New: func() any { return &Element[T]{} }} 18 } 19 20 // Element is an element of a linked list. 21 type Element[T any] struct { 22 // Next and previous pointers in the doubly-linked list of elements. 23 // To simplify the implementation, internally a list l is implemented 24 // as a ring, such that &l.root is both the next element of the last 25 // list element (l.Back()) and the previous element of the first list 26 // element (l.Front()). 27 next, prev *Element[T] 28 29 // The list to which this element belongs. 30 list *List[T] 31 32 // The value stored with this element. 33 Value T 34 } 35 36 // Next returns the next list element or nil. 37 func (e *Element[T]) Next() *Element[T] { 38 if p := e.next; e.list != nil && p != &e.list.root { 39 return p 40 } 41 return nil 42 } 43 44 // Prev returns the previous list element or nil. 45 func (e *Element[T]) Prev() *Element[T] { 46 if p := e.prev; e.list != nil && p != &e.list.root { 47 return p 48 } 49 return nil 50 } 51 52 func (e *Element[T]) List() *List[T] { 53 return e.list 54 } 55 56 // List represents a doubly linked list. 57 // The zero value for List is an empty list ready to use. 58 type List[T any] struct { 59 root Element[T] // sentinel list element, only &root, root.prev, and root.next are used 60 len int // current list length excluding (this) sentinel element 61 62 pool *sync.Pool 63 } 64 65 // Init initializes or clears list l. 66 func (l *List[T]) Init() *List[T] { 67 l.root.next = &l.root 68 l.root.prev = &l.root 69 l.len = 0 70 return l 71 } 72 73 // New returns an initialized list. 74 func New[T any]() *List[T] { return new(List[T]).Init() } 75 76 // NewWithPool returns an initialized list, using a sync.Pool for list elements. 77 func NewWithPool[T any](pool *sync.Pool) *List[T] { 78 l := &List[T]{pool: pool} 79 return l.Init() 80 } 81 82 // Len returns the number of elements of list l. 83 // The complexity is O(1). 84 func (l *List[T]) Len() int { return l.len } 85 86 // Front returns the first element of list l or nil if the list is empty. 87 func (l *List[T]) Front() *Element[T] { 88 if l.len == 0 { 89 return nil 90 } 91 return l.root.next 92 } 93 94 // Back returns the last element of list l or nil if the list is empty. 95 func (l *List[T]) Back() *Element[T] { 96 if l.len == 0 { 97 return nil 98 } 99 return l.root.prev 100 } 101 102 // lazyInit lazily initializes a zero List value. 103 func (l *List[T]) lazyInit() { 104 if l.root.next == nil { 105 l.Init() 106 } 107 } 108 109 // insert inserts e after at, increments l.len, and returns e. 110 func (l *List[T]) insert(e, at *Element[T]) *Element[T] { 111 e.prev = at 112 e.next = at.next 113 e.prev.next = e 114 e.next.prev = e 115 e.list = l 116 l.len++ 117 return e 118 } 119 120 // insertValue is a convenience wrapper for insert(&Element{Value: v}, at). 121 func (l *List[T]) insertValue(v T, at *Element[T]) *Element[T] { 122 var e *Element[T] 123 if l.pool != nil { 124 e = l.pool.Get().(*Element[T]) 125 } else { 126 e = &Element[T]{} 127 } 128 e.Value = v 129 return l.insert(e, at) 130 } 131 132 // remove removes e from its list, decrements l.len 133 func (l *List[T]) remove(e *Element[T]) { 134 e.prev.next = e.next 135 e.next.prev = e.prev 136 e.next = nil // avoid memory leaks 137 e.prev = nil // avoid memory leaks 138 e.list = nil 139 if l.pool != nil { 140 l.pool.Put(e) 141 } 142 l.len-- 143 } 144 145 // move moves e to next to at. 146 func (l *List[T]) move(e, at *Element[T]) { 147 if e == at { 148 return 149 } 150 e.prev.next = e.next 151 e.next.prev = e.prev 152 153 e.prev = at 154 e.next = at.next 155 e.prev.next = e 156 e.next.prev = e 157 } 158 159 // Remove removes e from l if e is an element of list l. 160 // It returns the element value e.Value. 161 // The element must not be nil. 162 func (l *List[T]) Remove(e *Element[T]) T { 163 v := e.Value 164 if e.list == l { 165 // if e.list == l, l must have been initialized when e was inserted 166 // in l or l == nil (e is a zero Element) and l.remove will crash 167 l.remove(e) 168 } 169 return v 170 } 171 172 // PushFront inserts a new element e with value v at the front of list l and returns e. 173 func (l *List[T]) PushFront(v T) *Element[T] { 174 l.lazyInit() 175 return l.insertValue(v, &l.root) 176 } 177 178 // PushBack inserts a new element e with value v at the back of list l and returns e. 179 func (l *List[T]) PushBack(v T) *Element[T] { 180 l.lazyInit() 181 return l.insertValue(v, l.root.prev) 182 } 183 184 // InsertBefore inserts a new element e with value v immediately before mark and returns e. 185 // If mark is not an element of l, the list is not modified. 186 // The mark must not be nil. 187 func (l *List[T]) InsertBefore(v T, mark *Element[T]) *Element[T] { 188 if mark.list != l { 189 return nil 190 } 191 // see comment in List.Remove about initialization of l 192 return l.insertValue(v, mark.prev) 193 } 194 195 // InsertAfter inserts a new element e with value v immediately after mark and returns e. 196 // If mark is not an element of l, the list is not modified. 197 // The mark must not be nil. 198 func (l *List[T]) InsertAfter(v T, mark *Element[T]) *Element[T] { 199 if mark.list != l { 200 return nil 201 } 202 // see comment in List.Remove about initialization of l 203 return l.insertValue(v, mark) 204 } 205 206 // MoveToFront moves element e to the front of list l. 207 // If e is not an element of l, the list is not modified. 208 // The element must not be nil. 209 func (l *List[T]) MoveToFront(e *Element[T]) { 210 if e.list != l || l.root.next == e { 211 return 212 } 213 // see comment in List.Remove about initialization of l 214 l.move(e, &l.root) 215 } 216 217 // MoveToBack moves element e to the back of list l. 218 // If e is not an element of l, the list is not modified. 219 // The element must not be nil. 220 func (l *List[T]) MoveToBack(e *Element[T]) { 221 if e.list != l || l.root.prev == e { 222 return 223 } 224 // see comment in List.Remove about initialization of l 225 l.move(e, l.root.prev) 226 } 227 228 // MoveBefore moves element e to its new position before mark. 229 // If e or mark is not an element of l, or e == mark, the list is not modified. 230 // The element and mark must not be nil. 231 func (l *List[T]) MoveBefore(e, mark *Element[T]) { 232 if e.list != l || e == mark || mark.list != l { 233 return 234 } 235 l.move(e, mark.prev) 236 } 237 238 // MoveAfter moves element e to its new position after mark. 239 // If e or mark is not an element of l, or e == mark, the list is not modified. 240 // The element and mark must not be nil. 241 func (l *List[T]) MoveAfter(e, mark *Element[T]) { 242 if e.list != l || e == mark || mark.list != l { 243 return 244 } 245 l.move(e, mark) 246 } 247 248 // PushBackList inserts a copy of another list at the back of list l. 249 // The lists l and other may be the same. They must not be nil. 250 func (l *List[T]) PushBackList(other *List[T]) { 251 l.lazyInit() 252 for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { 253 l.insertValue(e.Value, l.root.prev) 254 } 255 } 256 257 // PushFrontList inserts a copy of another list at the front of list l. 258 // The lists l and other may be the same. They must not be nil. 259 func (l *List[T]) PushFrontList(other *List[T]) { 260 l.lazyInit() 261 for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { 262 l.insertValue(e.Value, &l.root) 263 } 264 }