github.com/FlowerWrong/netstack@v0.0.0-20191009141956-e5848263af28/ilist/list.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package ilist provides the implementation of intrusive linked lists. 16 package ilist 17 18 // Linker is the interface that objects must implement if they want to be added 19 // to and/or removed from List objects. 20 // 21 // N.B. When substituted in a template instantiation, Linker doesn't need to 22 // be an interface, and in most cases won't be. 23 type Linker interface { 24 Next() Element 25 Prev() Element 26 SetNext(Element) 27 SetPrev(Element) 28 } 29 30 // Element the item that is used at the API level. 31 // 32 // N.B. Like Linker, this is unlikely to be an interface in most cases. 33 type Element interface { 34 Linker 35 } 36 37 // ElementMapper provides an identity mapping by default. 38 // 39 // This can be replaced to provide a struct that maps elements to linker 40 // objects, if they are not the same. An ElementMapper is not typically 41 // required if: Linker is left as is, Element is left as is, or Linker and 42 // Element are the same type. 43 type ElementMapper struct{} 44 45 // linkerFor maps an Element to a Linker. 46 // 47 // This default implementation should be inlined. 48 // 49 //go:nosplit 50 func (ElementMapper) linkerFor(elem Element) Linker { return elem } 51 52 // List is an intrusive list. Entries can be added to or removed from the list 53 // in O(1) time and with no additional memory allocations. 54 // 55 // The zero value for List is an empty list ready to use. 56 // 57 // To iterate over a list (where l is a List): 58 // for e := l.Front(); e != nil; e = e.Next() { 59 // // do something with e. 60 // } 61 // 62 // +stateify savable 63 type List struct { 64 head Element 65 tail Element 66 } 67 68 // Reset resets list l to the empty state. 69 func (l *List) Reset() { 70 l.head = nil 71 l.tail = nil 72 } 73 74 // Empty returns true iff the list is empty. 75 func (l *List) Empty() bool { 76 return l.head == nil 77 } 78 79 // Front returns the first element of list l or nil. 80 func (l *List) Front() Element { 81 return l.head 82 } 83 84 // Back returns the last element of list l or nil. 85 func (l *List) Back() Element { 86 return l.tail 87 } 88 89 // PushFront inserts the element e at the front of list l. 90 func (l *List) PushFront(e Element) { 91 ElementMapper{}.linkerFor(e).SetNext(l.head) 92 ElementMapper{}.linkerFor(e).SetPrev(nil) 93 94 if l.head != nil { 95 ElementMapper{}.linkerFor(l.head).SetPrev(e) 96 } else { 97 l.tail = e 98 } 99 100 l.head = e 101 } 102 103 // PushBack inserts the element e at the back of list l. 104 func (l *List) PushBack(e Element) { 105 ElementMapper{}.linkerFor(e).SetNext(nil) 106 ElementMapper{}.linkerFor(e).SetPrev(l.tail) 107 108 if l.tail != nil { 109 ElementMapper{}.linkerFor(l.tail).SetNext(e) 110 } else { 111 l.head = e 112 } 113 114 l.tail = e 115 } 116 117 // PushBackList inserts list m at the end of list l, emptying m. 118 func (l *List) PushBackList(m *List) { 119 if l.head == nil { 120 l.head = m.head 121 l.tail = m.tail 122 } else if m.head != nil { 123 ElementMapper{}.linkerFor(l.tail).SetNext(m.head) 124 ElementMapper{}.linkerFor(m.head).SetPrev(l.tail) 125 126 l.tail = m.tail 127 } 128 129 m.head = nil 130 m.tail = nil 131 } 132 133 // InsertAfter inserts e after b. 134 func (l *List) InsertAfter(b, e Element) { 135 a := ElementMapper{}.linkerFor(b).Next() 136 ElementMapper{}.linkerFor(e).SetNext(a) 137 ElementMapper{}.linkerFor(e).SetPrev(b) 138 ElementMapper{}.linkerFor(b).SetNext(e) 139 140 if a != nil { 141 ElementMapper{}.linkerFor(a).SetPrev(e) 142 } else { 143 l.tail = e 144 } 145 } 146 147 // InsertBefore inserts e before a. 148 func (l *List) InsertBefore(a, e Element) { 149 b := ElementMapper{}.linkerFor(a).Prev() 150 ElementMapper{}.linkerFor(e).SetNext(a) 151 ElementMapper{}.linkerFor(e).SetPrev(b) 152 ElementMapper{}.linkerFor(a).SetPrev(e) 153 154 if b != nil { 155 ElementMapper{}.linkerFor(b).SetNext(e) 156 } else { 157 l.head = e 158 } 159 } 160 161 // Remove removes e from l. 162 func (l *List) Remove(e Element) { 163 prev := ElementMapper{}.linkerFor(e).Prev() 164 next := ElementMapper{}.linkerFor(e).Next() 165 166 if prev != nil { 167 ElementMapper{}.linkerFor(prev).SetNext(next) 168 } else { 169 l.head = next 170 } 171 172 if next != nil { 173 ElementMapper{}.linkerFor(next).SetPrev(prev) 174 } else { 175 l.tail = prev 176 } 177 } 178 179 // Entry is a default implementation of Linker. Users can add anonymous fields 180 // of this type to their structs to make them automatically implement the 181 // methods needed by List. 182 // 183 // +stateify savable 184 type Entry struct { 185 next Element 186 prev Element 187 } 188 189 // Next returns the entry that follows e in the list. 190 func (e *Entry) Next() Element { 191 return e.next 192 } 193 194 // Prev returns the entry that precedes e in the list. 195 func (e *Entry) Prev() Element { 196 return e.prev 197 } 198 199 // SetNext assigns 'entry' as the entry that follows e in the list. 200 func (e *Entry) SetNext(elem Element) { 201 e.next = elem 202 } 203 204 // SetPrev assigns 'entry' as the entry that precedes e in the list. 205 func (e *Entry) SetPrev(elem Element) { 206 e.prev = elem 207 }