github.com/hdt3213/godis@v1.2.9/datastruct/list/quicklist.go (about) 1 package list 2 3 import "container/list" 4 5 // pageSize must be even 6 const pageSize = 1024 7 8 // QuickList is a linked list of page (which type is []interface{}) 9 // QuickList has better performance than LinkedList of Add, Range and memory usage 10 type QuickList struct { 11 data *list.List // list of []interface{} 12 size int 13 } 14 15 // iterator of QuickList, move between [-1, ql.Len()] 16 type iterator struct { 17 node *list.Element 18 offset int 19 ql *QuickList 20 } 21 22 func NewQuickList() *QuickList { 23 l := &QuickList{ 24 data: list.New(), 25 } 26 return l 27 } 28 29 // Add adds value to the tail 30 func (ql *QuickList) Add(val interface{}) { 31 ql.size++ 32 if ql.data.Len() == 0 { // empty list 33 page := make([]interface{}, 0, pageSize) 34 page = append(page, val) 35 ql.data.PushBack(page) 36 return 37 } 38 // assert list.data.Back() != nil 39 backNode := ql.data.Back() 40 backPage := backNode.Value.([]interface{}) 41 if len(backPage) == cap(backPage) { // full page, create new page 42 page := make([]interface{}, 0, pageSize) 43 page = append(page, val) 44 ql.data.PushBack(page) 45 return 46 } 47 // append into page 48 backPage = append(backPage, val) 49 backNode.Value = backPage 50 } 51 52 // find returns page and in-page-offset of given index 53 func (ql *QuickList) find(index int) *iterator { 54 if ql == nil { 55 panic("list is nil") 56 } 57 if index < 0 || index >= ql.size { 58 panic("index out of bound") 59 } 60 var n *list.Element 61 var page []interface{} 62 var pageBeg int 63 if index < ql.size/2 { 64 // search from front 65 n = ql.data.Front() 66 pageBeg = 0 67 for { 68 // assert: n != nil 69 page = n.Value.([]interface{}) 70 if pageBeg+len(page) > index { 71 break 72 } 73 pageBeg += len(page) 74 n = n.Next() 75 } 76 } else { 77 // search from back 78 n = ql.data.Back() 79 pageBeg = ql.size 80 for { 81 page = n.Value.([]interface{}) 82 pageBeg -= len(page) 83 if pageBeg <= index { 84 break 85 } 86 n = n.Prev() 87 } 88 } 89 pageOffset := index - pageBeg 90 return &iterator{ 91 node: n, 92 offset: pageOffset, 93 ql: ql, 94 } 95 } 96 97 func (iter *iterator) get() interface{} { 98 return iter.page()[iter.offset] 99 } 100 101 func (iter *iterator) page() []interface{} { 102 return iter.node.Value.([]interface{}) 103 } 104 105 // next returns whether iter is in bound 106 func (iter *iterator) next() bool { 107 page := iter.page() 108 if iter.offset < len(page)-1 { 109 iter.offset++ 110 return true 111 } 112 // move to next page 113 if iter.node == iter.ql.data.Back() { 114 // already at last node 115 iter.offset = len(page) 116 return false 117 } 118 iter.offset = 0 119 iter.node = iter.node.Next() 120 return true 121 } 122 123 // prev returns whether iter is in bound 124 func (iter *iterator) prev() bool { 125 if iter.offset > 0 { 126 iter.offset-- 127 return true 128 } 129 // move to prev page 130 if iter.node == iter.ql.data.Front() { 131 // already at first page 132 iter.offset = -1 133 return false 134 } 135 iter.node = iter.node.Prev() 136 prevPage := iter.node.Value.([]interface{}) 137 iter.offset = len(prevPage) - 1 138 return true 139 } 140 141 func (iter *iterator) atEnd() bool { 142 if iter.ql.data.Len() == 0 { 143 return true 144 } 145 if iter.node != iter.ql.data.Back() { 146 return false 147 } 148 page := iter.page() 149 return iter.offset == len(page) 150 } 151 152 func (iter *iterator) atBegin() bool { 153 if iter.ql.data.Len() == 0 { 154 return true 155 } 156 if iter.node != iter.ql.data.Front() { 157 return false 158 } 159 return iter.offset == -1 160 } 161 162 // Get returns value at the given index 163 func (ql *QuickList) Get(index int) (val interface{}) { 164 iter := ql.find(index) 165 return iter.get() 166 } 167 168 func (iter *iterator) set(val interface{}) { 169 page := iter.page() 170 page[iter.offset] = val 171 } 172 173 // Set updates value at the given index, the index should between [0, list.size] 174 func (ql *QuickList) Set(index int, val interface{}) { 175 iter := ql.find(index) 176 iter.set(val) 177 } 178 179 func (ql *QuickList) Insert(index int, val interface{}) { 180 if index == ql.size { // insert at 181 ql.Add(val) 182 return 183 } 184 iter := ql.find(index) 185 page := iter.node.Value.([]interface{}) 186 if len(page) < pageSize { 187 // insert into not full page 188 page = append(page[:iter.offset+1], page[iter.offset:]...) 189 page[iter.offset] = val 190 iter.node.Value = page 191 ql.size++ 192 return 193 } 194 // insert into a full page may cause memory copy, so we split a full page into two half pages 195 var nextPage []interface{} 196 nextPage = append(nextPage, page[pageSize/2:]...) // pageSize must be even 197 page = page[:pageSize/2] 198 if iter.offset < len(page) { 199 page = append(page[:iter.offset+1], page[iter.offset:]...) 200 page[iter.offset] = val 201 } else { 202 i := iter.offset - pageSize/2 203 nextPage = append(nextPage[:i+1], nextPage[i:]...) 204 nextPage[i] = val 205 } 206 // store current page and next page 207 iter.node.Value = page 208 ql.data.InsertAfter(nextPage, iter.node) 209 ql.size++ 210 } 211 212 func (iter *iterator) remove() interface{} { 213 page := iter.page() 214 val := page[iter.offset] 215 page = append(page[:iter.offset], page[iter.offset+1:]...) 216 if len(page) > 0 { 217 // page is not empty, update iter.offset only 218 iter.node.Value = page 219 if iter.offset == len(page) { 220 // removed page[-1], node should move to next page 221 if iter.node != iter.ql.data.Back() { 222 iter.node = iter.node.Next() 223 iter.offset = 0 224 } 225 // else: assert iter.atEnd() == true 226 } 227 } else { 228 // page is empty, update iter.node and iter.offset 229 if iter.node == iter.ql.data.Back() { 230 // removed last element, ql is empty now 231 iter.ql.data.Remove(iter.node) 232 iter.node = nil 233 iter.offset = 0 234 } else { 235 nextNode := iter.node.Next() 236 iter.ql.data.Remove(iter.node) 237 iter.node = nextNode 238 iter.offset = 0 239 } 240 } 241 iter.ql.size-- 242 return val 243 } 244 245 // Remove removes value at the given index 246 func (ql *QuickList) Remove(index int) interface{} { 247 iter := ql.find(index) 248 return iter.remove() 249 } 250 251 // Len returns the number of elements in list 252 func (ql *QuickList) Len() int { 253 return ql.size 254 } 255 256 // RemoveLast removes the last element and returns its value 257 func (ql *QuickList) RemoveLast() interface{} { 258 if ql.Len() == 0 { 259 return nil 260 } 261 ql.size-- 262 lastNode := ql.data.Back() 263 lastPage := lastNode.Value.([]interface{}) 264 if len(lastPage) == 1 { 265 ql.data.Remove(lastNode) 266 return lastPage[0] 267 } 268 val := lastPage[len(lastPage)-1] 269 lastPage = lastPage[:len(lastPage)-1] 270 lastNode.Value = lastPage 271 return val 272 } 273 274 // RemoveAllByVal removes all elements with the given val 275 func (ql *QuickList) RemoveAllByVal(expected Expected) int { 276 iter := ql.find(0) 277 removed := 0 278 for !iter.atEnd() { 279 if expected(iter.get()) { 280 iter.remove() 281 removed++ 282 } else { 283 iter.next() 284 } 285 } 286 return removed 287 } 288 289 // RemoveByVal removes at most `count` values of the specified value in this list 290 // scan from left to right 291 func (ql *QuickList) RemoveByVal(expected Expected, count int) int { 292 if ql.size == 0 { 293 return 0 294 } 295 iter := ql.find(0) 296 removed := 0 297 for !iter.atEnd() { 298 if expected(iter.get()) { 299 iter.remove() 300 removed++ 301 if removed == count { 302 break 303 } 304 } else { 305 iter.next() 306 } 307 } 308 return removed 309 } 310 311 func (ql *QuickList) ReverseRemoveByVal(expected Expected, count int) int { 312 if ql.size == 0 { 313 return 0 314 } 315 iter := ql.find(ql.size - 1) 316 removed := 0 317 for !iter.atBegin() { 318 if expected(iter.get()) { 319 iter.remove() 320 removed++ 321 if removed == count { 322 break 323 } 324 } 325 iter.prev() 326 } 327 return removed 328 } 329 330 // ForEach visits each element in the list 331 // if the consumer returns false, the loop will be break 332 func (ql *QuickList) ForEach(consumer Consumer) { 333 if ql == nil { 334 panic("list is nil") 335 } 336 if ql.Len() == 0 { 337 return 338 } 339 iter := ql.find(0) 340 i := 0 341 for { 342 goNext := consumer(i, iter.get()) 343 if !goNext { 344 break 345 } 346 i++ 347 if !iter.next() { 348 break 349 } 350 } 351 } 352 353 func (ql *QuickList) Contains(expected Expected) bool { 354 contains := false 355 ql.ForEach(func(i int, actual interface{}) bool { 356 if expected(actual) { 357 contains = true 358 return false 359 } 360 return true 361 }) 362 return contains 363 } 364 365 // Range returns elements which index within [start, stop) 366 func (ql *QuickList) Range(start int, stop int) []interface{} { 367 if start < 0 || start >= ql.Len() { 368 panic("`start` out of range") 369 } 370 if stop < start || stop > ql.Len() { 371 panic("`stop` out of range") 372 } 373 sliceSize := stop - start 374 slice := make([]interface{}, 0, sliceSize) 375 iter := ql.find(start) 376 i := 0 377 for i < sliceSize { 378 slice = append(slice, iter.get()) 379 iter.next() 380 i++ 381 } 382 return slice 383 }