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