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