github.com/wangyougui/gf/v2@v2.6.5/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/wangyougui/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/wangyougui/gf/v2/container/gtype" 14 "github.com/wangyougui/gf/v2/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 // internalRingItem stores the ring element value. 27 type internalRingItem struct { 28 Value interface{} 29 } 30 31 // New creates and returns a Ring structure of `cap` elements. 32 // The optional parameter `safe` specifies whether using this structure in concurrent safety, 33 // which is false in default. 34 func New(cap int, safe ...bool) *Ring { 35 return &Ring{ 36 mu: rwmutex.New(safe...), 37 ring: ring.New(cap), 38 len: gtype.NewInt(), 39 cap: gtype.NewInt(cap), 40 dirty: gtype.NewBool(), 41 } 42 } 43 44 // Val returns the item's value of current position. 45 func (r *Ring) Val() interface{} { 46 var value interface{} 47 r.mu.RLock() 48 if r.ring.Value != nil { 49 value = r.ring.Value.(internalRingItem).Value 50 } 51 r.mu.RUnlock() 52 return value 53 } 54 55 // Len returns the size of ring. 56 func (r *Ring) Len() int { 57 r.checkAndUpdateLenAndCap() 58 return r.len.Val() 59 } 60 61 // Cap returns the capacity of ring. 62 func (r *Ring) Cap() int { 63 r.checkAndUpdateLenAndCap() 64 return r.cap.Val() 65 } 66 67 // Checks and updates the len and cap of ring when ring is dirty. 68 func (r *Ring) checkAndUpdateLenAndCap() { 69 if !r.dirty.Val() { 70 return 71 } 72 r.mu.RLock() 73 defer r.mu.RUnlock() 74 totalLen := 0 75 emptyLen := 0 76 if r.ring != nil { 77 if r.ring.Value == nil { 78 emptyLen++ 79 } 80 totalLen++ 81 for p := r.ring.Next(); p != r.ring; p = p.Next() { 82 if p.Value == nil { 83 emptyLen++ 84 } 85 totalLen++ 86 } 87 } 88 r.cap.Set(totalLen) 89 r.len.Set(totalLen - emptyLen) 90 r.dirty.Set(false) 91 } 92 93 // Set sets value to the item of current position. 94 func (r *Ring) Set(value interface{}) *Ring { 95 r.mu.Lock() 96 if r.ring.Value == nil { 97 r.len.Add(1) 98 } 99 r.ring.Value = internalRingItem{Value: value} 100 r.mu.Unlock() 101 return r 102 } 103 104 // Put sets `value` to current item of ring and moves position to next item. 105 func (r *Ring) Put(value interface{}) *Ring { 106 r.mu.Lock() 107 if r.ring.Value == nil { 108 r.len.Add(1) 109 } 110 r.ring.Value = internalRingItem{Value: value} 111 r.ring = r.ring.Next() 112 r.mu.Unlock() 113 return r 114 } 115 116 // Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0) 117 // in the ring and returns that ring element. r must not be empty. 118 func (r *Ring) Move(n int) *Ring { 119 r.mu.Lock() 120 r.ring = r.ring.Move(n) 121 r.mu.Unlock() 122 return r 123 } 124 125 // Prev returns the previous ring element. r must not be empty. 126 func (r *Ring) Prev() *Ring { 127 r.mu.Lock() 128 r.ring = r.ring.Prev() 129 r.mu.Unlock() 130 return r 131 } 132 133 // Next returns the next ring element. r must not be empty. 134 func (r *Ring) Next() *Ring { 135 r.mu.Lock() 136 r.ring = r.ring.Next() 137 r.mu.Unlock() 138 return r 139 } 140 141 // Link connects ring r with ring s such that r.Next() 142 // becomes s and returns the original value for r.Next(). 143 // r must not be empty. 144 // 145 // If r and s point to the same ring, linking 146 // them removes the elements between r and s from the ring. 147 // The removed elements form a sub-ring and the result is a 148 // reference to that sub-ring (if no elements were removed, 149 // the result is still the original value for r.Next(), 150 // and not nil). 151 // 152 // If r and s point to different rings, linking 153 // them creates a single ring with the elements of s inserted 154 // after r. The result points to the element following the 155 // last element of s after insertion. 156 func (r *Ring) Link(s *Ring) *Ring { 157 r.mu.Lock() 158 s.mu.Lock() 159 r.ring.Link(s.ring) 160 s.mu.Unlock() 161 r.mu.Unlock() 162 r.dirty.Set(true) 163 s.dirty.Set(true) 164 return r 165 } 166 167 // Unlink removes n % r.Len() elements from the ring r, starting 168 // at r.Next(). If n % r.Len() == 0, r remains unchanged. 169 // The result is the removed sub-ring. r must not be empty. 170 func (r *Ring) Unlink(n int) *Ring { 171 r.mu.Lock() 172 resultRing := r.ring.Unlink(n) 173 r.dirty.Set(true) 174 r.mu.Unlock() 175 resultGRing := New(resultRing.Len()) 176 resultGRing.ring = resultRing 177 resultGRing.dirty.Set(true) 178 return resultGRing 179 } 180 181 // RLockIteratorNext iterates and locks reading forward 182 // with given callback function `f` within RWMutex.RLock. 183 // If `f` returns true, then it continues iterating; or false to stop. 184 func (r *Ring) RLockIteratorNext(f func(value interface{}) bool) { 185 r.mu.RLock() 186 defer r.mu.RUnlock() 187 if r.ring.Value != nil && !f(r.ring.Value.(internalRingItem).Value) { 188 return 189 } 190 for p := r.ring.Next(); p != r.ring; p = p.Next() { 191 if p.Value == nil || !f(p.Value.(internalRingItem).Value) { 192 break 193 } 194 } 195 } 196 197 // RLockIteratorPrev iterates and locks writing backward 198 // with given callback function `f` within RWMutex.RLock. 199 // If `f` returns true, then it continues iterating; or false to stop. 200 func (r *Ring) RLockIteratorPrev(f func(value interface{}) bool) { 201 r.mu.RLock() 202 defer r.mu.RUnlock() 203 if r.ring.Value != nil && !f(r.ring.Value.(internalRingItem).Value) { 204 return 205 } 206 for p := r.ring.Prev(); p != r.ring; p = p.Prev() { 207 if p.Value == nil || !f(p.Value.(internalRingItem).Value) { 208 break 209 } 210 } 211 } 212 213 // SliceNext returns a copy of all item values as slice forward from current position. 214 func (r *Ring) SliceNext() []interface{} { 215 s := make([]interface{}, 0) 216 r.mu.RLock() 217 if r.ring.Value != nil { 218 s = append(s, r.ring.Value.(internalRingItem).Value) 219 } 220 for p := r.ring.Next(); p != r.ring; p = p.Next() { 221 if p.Value == nil { 222 break 223 } 224 s = append(s, p.Value.(internalRingItem).Value) 225 } 226 r.mu.RUnlock() 227 return s 228 } 229 230 // SlicePrev returns a copy of all item values as slice backward from current position. 231 func (r *Ring) SlicePrev() []interface{} { 232 s := make([]interface{}, 0) 233 r.mu.RLock() 234 if r.ring.Value != nil { 235 s = append(s, r.ring.Value.(internalRingItem).Value) 236 } 237 for p := r.ring.Prev(); p != r.ring; p = p.Prev() { 238 if p.Value == nil { 239 break 240 } 241 s = append(s, p.Value.(internalRingItem).Value) 242 } 243 r.mu.RUnlock() 244 return s 245 }