gitee.com/h79/goutils@v1.22.10/common/queue/circular.go (about) 1 package queue 2 3 type ResetFunc func() 4 5 var _ Queue = (*Circular)(nil) 6 7 // Circular 环型队列 8 type Circular struct { 9 resetFunc ResetFunc 10 items []any 11 head int 12 tail int 13 size int 14 isFull bool 15 } 16 17 func NewCircular(size int, resetFunc ResetFunc) *Circular { 18 return &Circular{ 19 resetFunc: resetFunc, 20 items: make([]any, size), 21 size: size, 22 } 23 } 24 25 func (cr *Circular) Add(it any) error { 26 if cr.size == 0 { 27 return ErrIsReleased 28 } 29 if cr.isFull { 30 return ErrIsFull 31 } 32 cr.items[cr.tail] = it 33 cr.tail++ 34 35 if cr.tail == cr.size { 36 cr.tail = 0 37 } 38 if cr.tail == cr.head { 39 cr.isFull = true 40 } 41 return nil 42 } 43 44 func (cr *Circular) Push(it any) error { 45 return cr.Add(it) 46 } 47 48 func (cr *Circular) Pop() any { 49 if cr.Empty() { 50 return nil 51 } 52 w := cr.items[cr.head] 53 cr.items[cr.head] = nil 54 cr.head++ 55 if cr.head == cr.size { 56 cr.head = 0 57 } 58 cr.isFull = false 59 return w 60 } 61 62 func (cr *Circular) Peek() any { 63 if cr.Empty() { 64 return nil 65 } 66 return cr.items[cr.head] 67 } 68 69 func (cr *Circular) Len() int { 70 if cr.size == 0 { 71 return 0 72 } 73 74 if cr.head == cr.tail { 75 if cr.isFull { 76 return cr.size 77 } 78 return 0 79 } 80 81 if cr.tail > cr.head { 82 return cr.tail - cr.head 83 } 84 85 return cr.size - cr.head + cr.tail 86 } 87 88 // Find return index -1 not found. 89 func (cr *Circular) Find(fn IndexFunc) (any, int) { 90 var ( 91 cursor = -1 92 va any 93 ) 94 for { 95 va, cursor = cr.Next(cursor) 96 if cursor == -1 { 97 break 98 } 99 if fn(va, cursor) { 100 return va, cursor 101 } 102 } 103 return nil, -1 104 } 105 106 func (cr *Circular) Foreach(fn IndexFunc) { 107 var ( 108 cursor = -1 109 va any 110 ) 111 for { 112 va, cursor = cr.Next(cursor) 113 if cursor == -1 { 114 break 115 } 116 if fn(va, cursor) { 117 return 118 } 119 } 120 } 121 122 func (cr *Circular) Empty() bool { 123 return cr.head == cr.tail && !cr.isFull 124 } 125 126 func (cr *Circular) Next(index int) (any, int) { 127 if cr.Empty() { 128 return nil, -1 129 } 130 if index < 0 { 131 index = cr.head 132 } 133 if index == cr.tail { 134 return nil, -1 135 } 136 w := cr.items[index] 137 index++ 138 if index == cr.size { 139 index = 0 140 } 141 return w, index 142 } 143 144 func (cr *Circular) Reset() { 145 if cr.Empty() { 146 return 147 } 148 if cr.resetFunc != nil { 149 cr.resetFunc() 150 } 151 cr.items = make([]any, cr.size) 152 cr.head = 0 153 cr.tail = 0 154 }