github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zarray/list.go (about) 1 //go:build go1.18 2 // +build go1.18 3 4 package zarray 5 6 import ( 7 "sync/atomic" 8 "unsafe" 9 10 "github.com/sohaha/zlsgo/zutil" 11 ) 12 13 const ( 14 notDeleted uint32 = iota 15 deleted 16 ) 17 18 type atomicPointer[T any] struct { 19 _ zutil.Nocmp 20 ptr unsafe.Pointer 21 } 22 23 func (p *atomicPointer[T]) Load() *T { return (*T)(atomic.LoadPointer(&p.ptr)) } 24 func (p *atomicPointer[T]) Store(v *T) { atomic.StorePointer(&p.ptr, unsafe.Pointer(v)) } 25 func (p *atomicPointer[T]) Swap(v *T) *T { return (*T)(atomic.SwapPointer(&p.ptr, unsafe.Pointer(v))) } 26 func (p *atomicPointer[T]) CompareAndSwap(old, new *T) bool { 27 return atomic.CompareAndSwapPointer(&p.ptr, unsafe.Pointer(old), unsafe.Pointer(new)) 28 } 29 30 func newListHead[K hashable, V any]() *element[K, V] { 31 e := &element[K, V]{keyHash: 0, key: *new(K)} 32 e.nextPtr.Store(nil) 33 e.value.Store(new(V)) 34 return e 35 } 36 37 type element[K hashable, V any] struct { 38 key K 39 nextPtr atomicPointer[element[K, V]] 40 value atomicPointer[V] 41 keyHash uintptr 42 deleted uint32 43 } 44 45 func (self *element[K, V]) next() *element[K, V] { 46 for nextElement := self.nextPtr.Load(); nextElement != nil; { 47 if nextElement.isDeleted() { 48 self.nextPtr.CompareAndSwap(nextElement, nextElement.next()) 49 nextElement = self.nextPtr.Load() 50 } else { 51 return nextElement 52 } 53 } 54 return nil 55 } 56 57 func (self *element[K, V]) addBefore(allocatedElement, before *element[K, V]) bool { 58 if self.next() != before { 59 return false 60 } 61 allocatedElement.nextPtr.Store(before) 62 return self.nextPtr.CompareAndSwap(before, allocatedElement) 63 } 64 65 func (self *element[K, V]) inject(c uintptr, key K, value *V) (*element[K, V], bool) { 66 var ( 67 alloc *element[K, V] 68 left, curr, right = self.search(c, key) 69 ) 70 if curr != nil { 71 curr.value.Store(value) 72 return curr, false 73 } 74 if left != nil { 75 alloc = &element[K, V]{keyHash: c, key: key} 76 alloc.value.Store(value) 77 if left.addBefore(alloc, right) { 78 return alloc, true 79 } 80 } 81 return nil, false 82 } 83 84 func (self *element[K, V]) search(c uintptr, key K) (*element[K, V], *element[K, V], *element[K, V]) { 85 var ( 86 left, right *element[K, V] 87 curr = self 88 ) 89 for { 90 if curr == nil { 91 return left, curr, right 92 } 93 right = curr.next() 94 if c < curr.keyHash { 95 right = curr 96 curr = nil 97 return left, curr, right 98 } else if c == curr.keyHash && key == curr.key { 99 return left, curr, right 100 } 101 left = curr 102 curr = left.next() 103 right = nil 104 } 105 } 106 107 func (self *element[K, V]) remove() bool { 108 return atomic.CompareAndSwapUint32(&self.deleted, notDeleted, deleted) 109 } 110 111 func (self *element[K, V]) isDeleted() bool { 112 return atomic.LoadUint32(&self.deleted) == deleted 113 }