github.com/gogf/gf@v1.16.9/container/gring/gring.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 // Package gring provides a concurrent-safe/unsafe ring(circular lists). 8 package gring 9 10 import ( 11 "container/ring" 12 13 "github.com/gogf/gf/container/gtype" 14 "github.com/gogf/gf/internal/rwmutex" 15 ) 16 17 // Ring is a struct of ring structure. 18 type Ring struct { 19 mu *rwmutex.RWMutex 20 ring *ring.Ring // Underlying ring. 21 len *gtype.Int // Length(already used size). 22 cap *gtype.Int // Capability(>=len). 23 dirty *gtype.Bool // Dirty, which means the len and cap should be recalculated. It's marked dirty when the size of ring changes. 24 } 25 26 // New creates and returns a Ring structure of <cap> elements. 27 // The optional parameter <safe> specifies whether using this structure in concurrent safety, 28 // which is false in default. 29 func New(cap int, safe ...bool) *Ring { 30 return &Ring{ 31 mu: rwmutex.New(safe...), 32 ring: ring.New(cap), 33 len: gtype.NewInt(), 34 cap: gtype.NewInt(cap), 35 dirty: gtype.NewBool(), 36 } 37 } 38 39 // Val returns the item's value of current position. 40 func (r *Ring) Val() interface{} { 41 r.mu.RLock() 42 v := r.ring.Value 43 r.mu.RUnlock() 44 return v 45 } 46 47 // Len returns the size of ring. 48 func (r *Ring) Len() int { 49 r.checkAndUpdateLenAndCap() 50 return r.len.Val() 51 } 52 53 // Cap returns the capacity of ring. 54 func (r *Ring) Cap() int { 55 r.checkAndUpdateLenAndCap() 56 return r.cap.Val() 57 } 58 59 // Checks and updates the len and cap of ring when ring is dirty. 60 func (r *Ring) checkAndUpdateLenAndCap() { 61 if !r.dirty.Val() { 62 return 63 } 64 totalLen := 0 65 emptyLen := 0 66 if r.ring != nil { 67 r.mu.RLock() 68 for p := r.ring.Next(); p != r.ring; p = p.Next() { 69 if p.Value == nil { 70 emptyLen++ 71 } 72 totalLen++ 73 } 74 r.mu.RUnlock() 75 } 76 r.cap.Set(totalLen) 77 r.len.Set(totalLen - emptyLen) 78 r.dirty.Set(false) 79 } 80 81 // Set sets value to the item of current position. 82 func (r *Ring) Set(value interface{}) *Ring { 83 r.mu.Lock() 84 if r.ring.Value == nil { 85 r.len.Add(1) 86 } 87 r.ring.Value = value 88 r.mu.Unlock() 89 return r 90 } 91 92 // Put sets <value> to current item of ring and moves position to next item. 93 func (r *Ring) Put(value interface{}) *Ring { 94 r.mu.Lock() 95 if r.ring.Value == nil { 96 r.len.Add(1) 97 } 98 r.ring.Value = value 99 r.ring = r.ring.Next() 100 r.mu.Unlock() 101 return r 102 } 103 104 // Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0) 105 // in the ring and returns that ring element. r must not be empty. 106 func (r *Ring) Move(n int) *Ring { 107 r.mu.Lock() 108 r.ring = r.ring.Move(n) 109 r.mu.Unlock() 110 return r 111 } 112 113 // Prev returns the previous ring element. r must not be empty. 114 func (r *Ring) Prev() *Ring { 115 r.mu.Lock() 116 r.ring = r.ring.Prev() 117 r.mu.Unlock() 118 return r 119 } 120 121 // Next returns the next ring element. r must not be empty. 122 func (r *Ring) Next() *Ring { 123 r.mu.Lock() 124 r.ring = r.ring.Next() 125 r.mu.Unlock() 126 return r 127 } 128 129 // Link connects ring r with ring s such that r.Next() 130 // becomes s and returns the original value for r.Next(). 131 // r must not be empty. 132 // 133 // If r and s point to the same ring, linking 134 // them removes the elements between r and s from the ring. 135 // The removed elements form a subring and the result is a 136 // reference to that subring (if no elements were removed, 137 // the result is still the original value for r.Next(), 138 // and not nil). 139 // 140 // If r and s point to different rings, linking 141 // them creates a single ring with the elements of s inserted 142 // after r. The result points to the element following the 143 // last element of s after insertion. 144 // 145 func (r *Ring) Link(s *Ring) *Ring { 146 r.mu.Lock() 147 s.mu.Lock() 148 r.ring.Link(s.ring) 149 s.mu.Unlock() 150 r.mu.Unlock() 151 r.dirty.Set(true) 152 s.dirty.Set(true) 153 return r 154 } 155 156 // Unlink removes n % r.Len() elements from the ring r, starting 157 // at r.Next(). If n % r.Len() == 0, r remains unchanged. 158 // The result is the removed subring. r must not be empty. 159 // 160 func (r *Ring) Unlink(n int) *Ring { 161 r.mu.Lock() 162 r.ring = r.ring.Unlink(n) 163 r.dirty.Set(true) 164 r.mu.Unlock() 165 return r 166 } 167 168 // RLockIteratorNext iterates and locks reading forward 169 // with given callback function <f> within RWMutex.RLock. 170 // If <f> returns true, then it continues iterating; or false to stop. 171 func (r *Ring) RLockIteratorNext(f func(value interface{}) bool) { 172 r.mu.RLock() 173 defer r.mu.RUnlock() 174 if !f(r.ring.Value) { 175 return 176 } 177 for p := r.ring.Next(); p != r.ring; p = p.Next() { 178 if !f(p.Value) { 179 break 180 } 181 } 182 } 183 184 // RLockIteratorPrev iterates and locks reading backward 185 // with given callback function <f> within RWMutex.RLock. 186 // If <f> returns true, then it continues iterating; or false to stop. 187 func (r *Ring) RLockIteratorPrev(f func(value interface{}) bool) { 188 r.mu.RLock() 189 defer r.mu.RUnlock() 190 if !f(r.ring.Value) { 191 return 192 } 193 for p := r.ring.Prev(); p != r.ring; p = p.Prev() { 194 if !f(p.Value) { 195 break 196 } 197 } 198 } 199 200 // LockIteratorNext iterates and locks writing forward 201 // with given callback function <f> within RWMutex.RLock. 202 // If <f> returns true, then it continues iterating; or false to stop. 203 func (r *Ring) LockIteratorNext(f func(item *ring.Ring) bool) { 204 r.mu.RLock() 205 defer r.mu.RUnlock() 206 if !f(r.ring) { 207 return 208 } 209 for p := r.ring.Next(); p != r.ring; p = p.Next() { 210 if !f(p) { 211 break 212 } 213 } 214 } 215 216 // LockIteratorPrev iterates and locks writing backward 217 // with given callback function <f> within RWMutex.RLock. 218 // If <f> returns true, then it continues iterating; or false to stop. 219 func (r *Ring) LockIteratorPrev(f func(item *ring.Ring) bool) { 220 r.mu.RLock() 221 defer r.mu.RUnlock() 222 if !f(r.ring) { 223 return 224 } 225 for p := r.ring.Prev(); p != r.ring; p = p.Prev() { 226 if !f(p) { 227 break 228 } 229 } 230 } 231 232 // SliceNext returns a copy of all item values as slice forward from current position. 233 func (r *Ring) SliceNext() []interface{} { 234 s := make([]interface{}, 0) 235 r.mu.RLock() 236 if r.ring.Value != nil { 237 s = append(s, r.ring.Value) 238 } 239 for p := r.ring.Next(); p != r.ring; p = p.Next() { 240 if p.Value != nil { 241 s = append(s, p.Value) 242 } 243 } 244 r.mu.RUnlock() 245 return s 246 } 247 248 // SlicePrev returns a copy of all item values as slice backward from current position. 249 func (r *Ring) SlicePrev() []interface{} { 250 s := make([]interface{}, 0) 251 r.mu.RLock() 252 if r.ring.Value != nil { 253 s = append(s, r.ring.Value) 254 } 255 for p := r.ring.Prev(); p != r.ring; p = p.Prev() { 256 if p.Value != nil { 257 s = append(s, p.Value) 258 } 259 } 260 r.mu.RUnlock() 261 return s 262 }