github.com/aacfactory/rings@v1.1.2/ring.go (about) 1 /* 2 * Copyright 2021 Wang Min Xiang 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package rings 18 19 import ( 20 "bytes" 21 "sync" 22 ) 23 24 type node[E Entry] struct { 25 next, prev *node[E] 26 value E 27 } 28 29 func New[E Entry](key string, values ...E) (r *Ring[E]) { 30 r = &Ring[E]{ 31 mutex: sync.RWMutex{}, 32 key: key, 33 head: nil, 34 size: 0, 35 } 36 if values != nil && len(values) > 0 { 37 for _, value := range values { 38 r.Push(value) 39 } 40 } 41 return 42 } 43 44 type Ring[E Entry] struct { 45 mutex sync.RWMutex 46 key string 47 head *node[E] 48 size int 49 } 50 51 func (r *Ring[E]) Key() (key string) { 52 key = r.key 53 return 54 } 55 56 func (r *Ring[E]) Push(v E) (ok bool) { 57 r.mutex.Lock() 58 _, has := r.get(v.Key()) 59 if has { 60 r.mutex.Unlock() 61 return 62 } 63 e := &node[E]{ 64 value: v, 65 } 66 if r.head == nil { 67 e.next = e 68 e.prev = e 69 r.head = e 70 } else { 71 prev := r.head.prev 72 prev.next = e 73 e.prev = prev 74 e.next = r.head 75 r.head.prev = e 76 } 77 r.size++ 78 ok = true 79 r.mutex.Unlock() 80 return 81 } 82 83 func (r *Ring[E]) Pop() (e E, ok bool) { 84 r.mutex.Lock() 85 if r.head == nil { 86 r.mutex.Unlock() 87 return 88 } 89 head := r.head 90 e = head.value 91 r.size-- 92 if r.size == 0 { 93 head = nil 94 } else { 95 next := head.next 96 next.prev = head.prev 97 head = next 98 } 99 r.head = head 100 r.mutex.Unlock() 101 return 102 } 103 104 func (r *Ring[E]) Remove(key string) { 105 r.mutex.Lock() 106 if r.head == nil { 107 r.mutex.Unlock() 108 return 109 } 110 head := r.head 111 for i := 0; i < r.size; i++ { 112 e := r.next() 113 if e.value.Key() == key { 114 if e.prev.value.Key() == key && e.next.value.Key() == key { 115 head = nil 116 break 117 } 118 prev := e.prev 119 next := e.next 120 prev.next = next 121 if head.value.Key() == key { 122 head = next 123 } 124 break 125 } 126 } 127 r.head = head 128 r.size-- 129 r.mutex.Unlock() 130 } 131 132 func (r *Ring[E]) Next() (value E) { 133 r.mutex.RLock() 134 if r.size == 0 { 135 r.mutex.RUnlock() 136 return 137 } 138 value = r.next().value 139 r.mutex.RUnlock() 140 return 141 } 142 143 func (r *Ring[E]) SeekTo(key string) (has bool) { 144 r.mutex.RLock() 145 if r.size == 0 { 146 r.mutex.RUnlock() 147 return 148 } 149 for i := 0; i < r.size; i++ { 150 n := r.next() 151 if n.value.Key() == key { 152 r.head = n 153 has = true 154 break 155 } 156 } 157 r.mutex.RUnlock() 158 return 159 } 160 161 func (r *Ring[E]) Head() (value E, has bool) { 162 r.mutex.RLock() 163 if r.size == 0 { 164 r.mutex.RUnlock() 165 return 166 } 167 value = r.head.value 168 has = true 169 r.mutex.RUnlock() 170 return 171 } 172 173 func (r *Ring[E]) Get(key string) (value E, has bool) { 174 r.mutex.RLock() 175 if r.size == 0 { 176 r.mutex.RUnlock() 177 return 178 } 179 var n *node[E] = nil 180 n, has = r.get(key) 181 if has { 182 value = n.value 183 } 184 r.mutex.RUnlock() 185 return 186 } 187 188 func (r *Ring[E]) get(key string) (value *node[E], has bool) { 189 if r.size == 0 { 190 return 191 } 192 head := r.head 193 for i := 0; i < r.size; i++ { 194 n := r.next() 195 if n.value.Key() == key { 196 value = n 197 has = true 198 break 199 } 200 } 201 r.head = head 202 return 203 } 204 205 func (r *Ring[E]) Len() (size int) { 206 r.mutex.RLock() 207 size = r.size 208 r.mutex.RUnlock() 209 return 210 } 211 212 func (r *Ring[E]) String() (value string) { 213 r.mutex.RLock() 214 p := bytes.NewBufferString("") 215 _ = p.WriteByte('[') 216 for i := 0; i < r.size; i++ { 217 e := r.next() 218 if i == 0 { 219 _, _ = p.WriteString(e.value.Key()) 220 } else { 221 _, _ = p.WriteString(", ") 222 _, _ = p.WriteString(e.value.Key()) 223 } 224 } 225 _ = p.WriteByte(']') 226 value = p.String() 227 r.mutex.RUnlock() 228 return 229 } 230 231 func (r *Ring[E]) next() (node *node[E]) { 232 node = r.head 233 r.head = r.head.next 234 return 235 }