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