github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/ilist/interface_list.go (about) 1 package ilist 2 3 // Linker is the interface that objects must implement if they want to be added 4 // to and/or removed from List objects. 5 // 6 // N.B. When substituted in a template instantiation, Linker doesn't need to 7 // be an interface, and in most cases won't be. 8 type Linker interface { 9 Next() Element 10 Prev() Element 11 SetNext(Element) 12 SetPrev(Element) 13 } 14 15 // Element the item that is used at the API level. 16 // 17 // N.B. Like Linker, this is unlikely to be an interface in most cases. 18 type Element interface { 19 Linker 20 } 21 22 // ElementMapper provides an identity mapping by default. 23 // 24 // This can be replaced to provide a struct that maps elements to linker 25 // objects, if they are not the same. An ElementMapper is not typically 26 // required if: Linker is left as is, Element is left as is, or Linker and 27 // Element are the same type. 28 type ElementMapper struct{} 29 30 // linkerFor maps an Element to a Linker. 31 // 32 // This default implementation should be inlined. 33 // 34 //go:nosplit 35 func (ElementMapper) linkerFor(elem Element) Linker { return elem } 36 37 // List is an intrusive list. Entries can be added to or removed from the list 38 // in O(1) time and with no additional memory allocations. 39 // 40 // The zero value for List is an empty list ready to use. 41 // 42 // To iterate over a list (where l is a List): 43 // 44 // for e := l.Front(); e != nil; e = e.Next() { 45 // // do something with e. 46 // } 47 // 48 // +stateify savable 49 type List struct { 50 head Element 51 tail Element 52 } 53 54 // Reset resets list l to the empty state. 55 func (l *List) Reset() { 56 l.head = nil 57 l.tail = nil 58 } 59 60 // Empty returns true iff the list is empty. 61 // 62 //go:nosplit 63 func (l *List) Empty() bool { 64 return l.head == nil 65 } 66 67 // Front returns the first element of list l or nil. 68 // 69 //go:nosplit 70 func (l *List) Front() Element { 71 return l.head 72 } 73 74 // Back returns the last element of list l or nil. 75 // 76 //go:nosplit 77 func (l *List) Back() Element { 78 return l.tail 79 } 80 81 // Len returns the number of elements in the list. 82 // 83 // NOTE: This is an O(n) operation. 84 // 85 //go:nosplit 86 func (l *List) Len() (count int) { 87 for e := l.Front(); e != nil; e = (ElementMapper{}.linkerFor(e)).Next() { 88 count++ 89 } 90 return count 91 } 92 93 // PushFront inserts the element e at the front of list l. 94 // 95 //go:nosplit 96 func (l *List) PushFront(e Element) { 97 linker := ElementMapper{}.linkerFor(e) 98 linker.SetNext(l.head) 99 linker.SetPrev(nil) 100 if l.head != nil { 101 ElementMapper{}.linkerFor(l.head).SetPrev(e) 102 } else { 103 l.tail = e 104 } 105 106 l.head = e 107 } 108 109 // PushFrontList inserts list m at the start of list l, emptying m. 110 // 111 //go:nosplit 112 func (l *List) PushFrontList(m *List) { 113 if l.head == nil { 114 l.head = m.head 115 l.tail = m.tail 116 } else if m.head != nil { 117 ElementMapper{}.linkerFor(l.head).SetPrev(m.tail) 118 ElementMapper{}.linkerFor(m.tail).SetNext(l.head) 119 120 l.head = m.head 121 } 122 m.head = nil 123 m.tail = nil 124 } 125 126 // PushBack inserts the element e at the back of list l. 127 // 128 //go:nosplit 129 func (l *List) PushBack(e Element) { 130 linker := ElementMapper{}.linkerFor(e) 131 linker.SetNext(nil) 132 linker.SetPrev(l.tail) 133 if l.tail != nil { 134 ElementMapper{}.linkerFor(l.tail).SetNext(e) 135 } else { 136 l.head = e 137 } 138 139 l.tail = e 140 } 141 142 // PushBackList inserts list m at the end of list l, emptying m. 143 // 144 //go:nosplit 145 func (l *List) PushBackList(m *List) { 146 if l.head == nil { 147 l.head = m.head 148 l.tail = m.tail 149 } else if m.head != nil { 150 ElementMapper{}.linkerFor(l.tail).SetNext(m.head) 151 ElementMapper{}.linkerFor(m.head).SetPrev(l.tail) 152 153 l.tail = m.tail 154 } 155 m.head = nil 156 m.tail = nil 157 } 158 159 // InsertAfter inserts e after b. 160 // 161 //go:nosplit 162 func (l *List) InsertAfter(b, e Element) { 163 bLinker := ElementMapper{}.linkerFor(b) 164 eLinker := ElementMapper{}.linkerFor(e) 165 166 a := bLinker.Next() 167 168 eLinker.SetNext(a) 169 eLinker.SetPrev(b) 170 bLinker.SetNext(e) 171 172 if a != nil { 173 ElementMapper{}.linkerFor(a).SetPrev(e) 174 } else { 175 l.tail = e 176 } 177 } 178 179 // InsertBefore inserts e before a. 180 // 181 //go:nosplit 182 func (l *List) InsertBefore(a, e Element) { 183 aLinker := ElementMapper{}.linkerFor(a) 184 eLinker := ElementMapper{}.linkerFor(e) 185 186 b := aLinker.Prev() 187 eLinker.SetNext(a) 188 eLinker.SetPrev(b) 189 aLinker.SetPrev(e) 190 191 if b != nil { 192 ElementMapper{}.linkerFor(b).SetNext(e) 193 } else { 194 l.head = e 195 } 196 } 197 198 // Remove removes e from l. 199 // 200 //go:nosplit 201 func (l *List) Remove(e Element) { 202 linker := ElementMapper{}.linkerFor(e) 203 prev := linker.Prev() 204 next := linker.Next() 205 206 if prev != nil { 207 ElementMapper{}.linkerFor(prev).SetNext(next) 208 } else if l.head == e { 209 l.head = next 210 } 211 212 if next != nil { 213 ElementMapper{}.linkerFor(next).SetPrev(prev) 214 } else if l.tail == e { 215 l.tail = prev 216 } 217 218 linker.SetNext(nil) 219 linker.SetPrev(nil) 220 } 221 222 // Entry is a default implementation of Linker. Users can add anonymous fields 223 // of this type to their structs to make them automatically implement the 224 // methods needed by List. 225 // 226 // +stateify savable 227 type Entry struct { 228 next Element 229 prev Element 230 } 231 232 // Next returns the entry that follows e in the list. 233 // 234 //go:nosplit 235 func (e *Entry) Next() Element { 236 return e.next 237 } 238 239 // Prev returns the entry that precedes e in the list. 240 // 241 //go:nosplit 242 func (e *Entry) Prev() Element { 243 return e.prev 244 } 245 246 // SetNext assigns 'entry' as the entry that follows e in the list. 247 // 248 //go:nosplit 249 func (e *Entry) SetNext(elem Element) { 250 e.next = elem 251 } 252 253 // SetPrev assigns 'entry' as the entry that precedes e in the list. 254 // 255 //go:nosplit 256 func (e *Entry) SetPrev(elem Element) { 257 e.prev = elem 258 }