github.com/coocood/badger@v1.5.1-0.20200528065104-c02ac3616d04/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  }