github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/ds/ring.go (about) 1 package ds 2 3 import ( 4 "github.com/15mga/kiwi/util" 5 ) 6 7 type ( 8 ringOption[T any] struct { 9 maxCap int 10 minCap int 11 shrinkCount int 12 slow int 13 resize func(int) 14 } 15 RingOption[T any] func(o *ringOption[T]) 16 ) 17 18 func RingMaxCap[T any](c int) RingOption[T] { 19 return func(o *ringOption[T]) { 20 o.maxCap = c 21 } 22 } 23 24 func RingMinCap[T any](c int) RingOption[T] { 25 return func(o *ringOption[T]) { 26 o.minCap = c 27 } 28 } 29 30 func RingResize[T any](r func(int)) RingOption[T] { 31 return func(o *ringOption[T]) { 32 o.resize = r 33 } 34 } 35 36 func RingSlow[T any](r func(int)) RingOption[T] { 37 return func(o *ringOption[T]) { 38 o.resize = r 39 } 40 } 41 42 func NewRing[T any](opts ...RingOption[T]) *Ring[T] { 43 opt := &ringOption[T]{ 44 maxCap: 0, 45 minCap: 32, 46 shrinkCount: 64, 47 slow: 1024, 48 } 49 for _, o := range opts { 50 o(opt) 51 } 52 r := &Ring[T]{ 53 opt: opt, 54 buffer: make([]T, opt.minCap), 55 bufferCap: opt.minCap, 56 halfBuffCap: opt.minCap >> 1, 57 shrink: opt.shrinkCount, 58 } 59 r.defVal = r.buffer[0] 60 return r 61 } 62 63 type Ring[T any] struct { 64 opt *ringOption[T] 65 defVal T 66 available int 67 readIdx int 68 writeIdx int 69 buffer []T 70 bufferCap int 71 halfBuffCap int 72 shrink int 73 } 74 75 func (r *Ring[T]) Available() int { 76 return r.available 77 } 78 79 func (r *Ring[T]) testCap(c int) *util.Err { 80 if c > r.bufferCap { 81 c, ok := util.NextCap(c, r.bufferCap, r.opt.slow) 82 if ok { 83 if r.opt.maxCap > 0 && c >= r.opt.maxCap { 84 return util.NewErr(util.EcTooLong, util.M{ 85 "total": c, 86 }) 87 } 88 r.resetBuffer(c) 89 } 90 return nil 91 } 92 if r.opt.minCap == r.bufferCap { 93 return nil 94 } 95 if c > r.halfBuffCap { 96 r.shrink = r.opt.shrinkCount 97 return nil 98 } 99 r.shrink-- 100 if r.shrink > 0 { 101 return nil 102 } 103 r.resetBuffer(r.halfBuffCap) 104 return nil 105 } 106 107 func (r *Ring[T]) resetBuffer(cap int) { 108 buf := make([]T, cap) 109 if r.available > 0 { 110 if r.writeIdx > r.readIdx { 111 copy(buf, r.buffer[r.readIdx:r.writeIdx]) 112 } else { 113 n := copy(buf, r.buffer[r.readIdx:]) 114 copy(buf[n:], r.buffer[:r.writeIdx]) 115 } 116 } 117 r.writeIdx = r.available 118 r.readIdx = 0 119 r.bufferCap = cap 120 r.halfBuffCap = cap >> 1 121 r.buffer = buf 122 r.shrink = r.opt.shrinkCount 123 if r.opt.resize != nil { 124 r.opt.resize(cap) 125 } 126 } 127 128 func (r *Ring[T]) Put(items ...T) *util.Err { 129 l := len(items) 130 c := r.available + l 131 err := r.testCap(c) 132 if err != nil { 133 return err 134 } 135 r.available = c 136 i := r.writeIdx + l 137 if i <= r.bufferCap { 138 copy(r.buffer[r.writeIdx:], items) 139 r.writeIdx = i 140 } else { 141 copy(r.buffer[r.writeIdx:r.bufferCap], items) 142 j := r.bufferCap - r.writeIdx 143 copy(r.buffer, items[j:l]) 144 r.writeIdx = l - j 145 } 146 return nil 147 } 148 149 func (r *Ring[T]) Pop() (item T, err *util.Err) { 150 if r.available == 0 { 151 return util.Default[T](), util.NewErr(util.EcNotEnough, util.M{ 152 "available": r.available, 153 }) 154 } 155 item = r.buffer[r.readIdx] 156 r.readIdx++ 157 if r.readIdx == r.bufferCap { 158 r.readIdx = 0 159 } 160 r.available-- 161 return 162 } 163 164 func (r *Ring[T]) Read(s []T, l int) *util.Err { 165 sl := len(s) 166 if l > sl || l > r.available { 167 return util.NewErr(util.EcNotEnough, util.M{ 168 "length": l, 169 "slice": sl, 170 "available": r.available, 171 }) 172 } 173 r.read(s, l) 174 return nil 175 } 176 177 func (r *Ring[T]) read(s []T, l int) { 178 p := r.readIdx + l 179 if p < r.bufferCap { 180 copy(s, r.buffer[r.readIdx:p]) 181 r.readIdx = p 182 } else { 183 p -= r.bufferCap 184 copy(s, r.buffer[r.readIdx:r.bufferCap]) 185 copy(s[r.bufferCap-r.readIdx:], r.buffer[:p]) 186 r.readIdx = p 187 } 188 r.available -= l 189 } 190 191 func (r *Ring[T]) ReadMax(s []T) int { 192 l := util.MaxInt(len(s), r.available) 193 r.read(s, l) 194 return l 195 } 196 197 func (r *Ring[T]) IterAll(fn func(T)) { 198 if r.readIdx < r.writeIdx { 199 for ; r.readIdx < r.writeIdx; r.readIdx++ { 200 fn(r.buffer[r.readIdx]) 201 } 202 return 203 } 204 for ; r.readIdx < r.bufferCap; r.readIdx++ { 205 fn(r.buffer[r.readIdx]) 206 } 207 for r.readIdx = 0; r.readIdx < r.writeIdx; r.readIdx++ { 208 fn(r.buffer[r.readIdx]) 209 } 210 } 211 212 func (r *Ring[T]) Iter(fn func([]T)) { 213 if r.readIdx == r.writeIdx { 214 return 215 } 216 if r.readIdx < r.writeIdx { 217 fn(r.buffer[r.readIdx:r.writeIdx]) 218 return 219 } 220 fn(r.buffer[r.readIdx:]) 221 fn(r.buffer[:r.writeIdx]) 222 } 223 224 func (r *Ring[T]) Reset() { 225 r.readIdx = 0 226 r.writeIdx = 0 227 }