github.com/pingcap/badger@v1.5.1-0.20230103063557-828f39b09b6d/epoch/list.go (about) 1 package epoch 2 3 import ( 4 "sync/atomic" 5 "unsafe" 6 ) 7 8 type guardList struct { 9 head unsafe.Pointer 10 } 11 12 func (l *guardList) add(g *Guard) { 13 for { 14 head := atomic.LoadPointer(&l.head) 15 g.next = head 16 if atomic.CompareAndSwapPointer(&l.head, head, unsafe.Pointer(g)) { 17 return 18 } 19 } 20 } 21 22 func (l *guardList) iterate(f func(*Guard) bool) { 23 loc := &l.head 24 curr := (*Guard)(atomic.LoadPointer(&l.head)) 25 26 for curr != nil { 27 delete := f(curr) 28 29 next := curr.next 30 // if current node is the head of list when start iteration 31 // we cannot delete it from list, because the `it.list.head` may 32 // point to a new node, if `it.loc` is updated we will lost the newly added nodes. 33 if delete && loc != &l.head { 34 *loc = next 35 } else { 36 loc = &curr.next 37 } 38 curr = (*Guard)(next) 39 } 40 }