github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/znet/limiter/queue.go (about) 1 package limiter 2 3 import ( 4 "errors" 5 "sync" 6 "time" 7 ) 8 9 type circleQueue struct { 10 slice []int64 11 maxSize int 12 head int 13 tail int 14 sync.RWMutex 15 } 16 17 // newCircleQueue Initialize ring queue 18 func newCircleQueue(size int) *circleQueue { 19 var c circleQueue 20 c.maxSize = size + 1 21 c.slice = make([]int64, c.maxSize) 22 return &c 23 } 24 25 func (c *circleQueue) push(val int64) (err error) { 26 if c.isFull() { 27 return errors.New("queue is full") 28 } 29 c.slice[c.tail] = val 30 c.tail = (c.tail + 1) % c.maxSize 31 return 32 } 33 34 func (c *circleQueue) pop() (val int64, err error) { 35 if c.isEmpty() { 36 return 0, errors.New("queue is empty") 37 } 38 c.Lock() 39 defer c.Unlock() 40 val = c.slice[c.head] 41 c.head = (c.head + 1) % c.maxSize 42 return 43 } 44 45 func (c *circleQueue) isFull() bool { 46 return (c.tail+1)%c.maxSize == c.head 47 } 48 49 func (c *circleQueue) isEmpty() bool { 50 return c.tail == c.head 51 } 52 53 func (c *circleQueue) usedSize() int { 54 c.RLock() 55 defer c.RUnlock() 56 return (c.tail + c.maxSize - c.head) % c.maxSize 57 } 58 59 func (c *circleQueue) unUsedSize() int { 60 return c.maxSize - 1 - c.usedSize() 61 } 62 63 func (c *circleQueue) size() int { 64 return c.maxSize - 1 65 } 66 67 func (c *circleQueue) deleteExpired() { 68 now := time.Now().UnixNano() 69 size := c.usedSize() 70 if size == 0 { 71 return 72 } 73 for i := 0; i < size; i++ { 74 if now > c.slice[c.head] { 75 _, _ = c.pop() 76 } else { 77 return 78 } 79 } 80 }