github.com/cloudwego/kitex@v0.9.0/pkg/utils/ring_single.go (about) 1 /* 2 * Copyright 2021 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package utils 18 19 import "sync" 20 21 // ring implements a fixed size ring buffer to manage data 22 type ring struct { 23 l sync.RWMutex 24 arr []interface{} 25 size int 26 tail int 27 head int 28 } 29 30 // newRing creates a ringbuffer with fixed size. 31 func newRing(size int) *ring { 32 if size <= 0 { 33 // When size is an invalid number, we still return an instance 34 // with zero-size to reduce error checks of the callers. 35 size = 0 36 } 37 return &ring{ 38 arr: make([]interface{}, size+1), 39 size: size, 40 } 41 } 42 43 // Push appends item to the ring. 44 func (r *ring) Push(i interface{}) error { 45 r.l.Lock() 46 defer r.l.Unlock() 47 if r.isFull() { 48 return ErrRingFull 49 } 50 r.arr[r.head] = i 51 r.head = r.inc() 52 return nil 53 } 54 55 // Pop returns the last item and removes it from the ring. 56 func (r *ring) Pop() interface{} { 57 r.l.Lock() 58 defer r.l.Unlock() 59 if r.isEmpty() { 60 return nil 61 } 62 c := r.arr[r.tail] 63 r.arr[r.tail] = nil 64 r.tail = r.dec() 65 return c 66 } 67 68 type ringDump struct { 69 Array []interface{} `json:"array"` 70 Len int `json:"len"` 71 Cap int `json:"cap"` 72 } 73 74 // Dump dumps the data in the ring. 75 func (r *ring) Dump(m *ringDump) { 76 r.l.RLock() 77 defer r.l.RUnlock() 78 m.Cap = r.size + 1 79 m.Len = (r.head - r.tail + r.size + 1) % (r.size + 1) 80 m.Array = make([]interface{}, 0, m.Len) 81 for i := 0; i < m.Len; i++ { 82 m.Array = append(m.Array, r.arr[(r.tail+i)%(r.size+1)]) 83 } 84 } 85 86 func (r *ring) inc() int { 87 return (r.head + 1) % (r.size + 1) 88 } 89 90 func (r *ring) dec() int { 91 return (r.tail + 1) % (r.size + 1) 92 } 93 94 func (r *ring) isEmpty() bool { 95 return r.tail == r.head 96 } 97 98 func (r *ring) isFull() bool { 99 return r.inc() == r.tail 100 }