github.com/aacfactory/rings@v1.1.2/immutable.go (about) 1 package rings 2 3 import ( 4 "bytes" 5 "fmt" 6 "math" 7 "unsafe" 8 ) 9 10 func NewImmutable[E Entry](key string, values []E) (r *ImmutableRing[E]) { 11 if values == nil || len(values) == 0 { 12 panic(fmt.Errorf("new immutable ring failed, cause values is nil or empty")) 13 return 14 } 15 keys := make(map[string]int) 16 for _, value := range values { 17 n := keys[value.Key()] 18 n++ 19 keys[value.Key()] = n 20 } 21 err := "" 22 for vk, n := range keys { 23 if n > 1 { 24 err = err + ", " + vk 25 } 26 } 27 if err != "" { 28 panic(fmt.Errorf("new immutable ring failed cause [%s] has duplicated", err[2:])) 29 return 30 } 31 valuesLen := uint32(len(values)) 32 capacity := uint32(0) 33 doubleTimes := uint32(1) 34 for { 35 capacity = uint32(math.Pow(float64(2), float64(doubleTimes))) 36 if capacity >= valuesLen { 37 break 38 } 39 doubleTimes++ 40 } 41 filledValues := make([]E, capacity) 42 for i := uint32(0); i < capacity; i++ { 43 idx := i % valuesLen 44 filledValues[i] = values[idx] 45 } 46 47 var elements []*element[E] = nil 48 align := uint32(unsafe.Alignof(elements)) 49 mask := capacity - 1 50 shift := uint32(math.Log2(float64(capacity))) 51 elements = make([]*element[E], capacity*align) 52 for i := range elements { 53 elements[i] = &element[E]{} 54 } 55 56 elementBasePtr := uintptr(unsafe.Pointer(&elements[0])) 57 elementMSize := unsafe.Sizeof(elements[0]) 58 59 r = &ImmutableRing[E]{ 60 key: key, 61 sequence: NewSequence(), 62 size: capacity, 63 shift: shift, 64 align: align, 65 mask: mask, 66 elements: elements, 67 elementBasePtr: elementBasePtr, 68 elementMSize: elementMSize, 69 } 70 71 for i := uint32(0); i < capacity; i++ { 72 r.elementAt(i).value = filledValues[i] 73 } 74 75 return 76 } 77 78 type ImmutableRing[E Entry] struct { 79 sequence *Sequence 80 elements []*element[E] 81 size uint32 82 shift uint32 83 align uint32 84 mask uint32 85 elementBasePtr uintptr 86 elementMSize uintptr 87 key string 88 } 89 90 func (r *ImmutableRing[E]) Key() (key string) { 91 key = r.key 92 return 93 } 94 95 func (r *ImmutableRing[E]) Next() (value E) { 96 idx := r.sequence.Next() % r.size 97 e := r.elementAt(idx) 98 value = e.value 99 return 100 } 101 102 func (r *ImmutableRing[E]) Head() (value E, has bool) { 103 e := r.elementAt(r.sequence.Value()) 104 value = e.value 105 has = true 106 return 107 } 108 109 func (r *ImmutableRing[E]) Get(key string) (value E, has bool) { 110 for i := uint32(0); i < r.size; i++ { 111 e := r.elementAt(i) 112 if e.value.Key() == key { 113 value = e.value 114 has = true 115 break 116 } 117 } 118 return 119 } 120 121 func (r *ImmutableRing[E]) String() (value string) { 122 p := bytes.NewBufferString("") 123 _ = p.WriteByte('[') 124 for i := uint32(0); i < r.size; i++ { 125 e := r.elementAt(i) 126 if i == 0 { 127 _, _ = p.WriteString(e.value.Key()) 128 } else { 129 _, _ = p.WriteString(", ") 130 _, _ = p.WriteString(e.value.Key()) 131 } 132 } 133 _ = p.WriteByte(']') 134 value = p.String() 135 return 136 } 137 138 func (r *ImmutableRing[E]) elementAt(idx uint32) (e *element[E]) { 139 elementPtr := r.elementBasePtr + uintptr(idx&r.mask*r.align)*r.elementMSize 140 e = *((*(*element[E]))(unsafe.Pointer(elementPtr))) 141 return 142 } 143 144 type element[E Entry] struct { 145 value E 146 }