github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/list/x_com_skl.go (about) 1 package list 2 3 import ( 4 "cmp" 5 "sync/atomic" 6 7 "github.com/benz9527/xboot/lib/infra" 8 ) 9 10 var _ XSkipList[uint8, uint8] = (*xComSkl[uint8, uint8])(nil) 11 12 // A common (not thread safe) implementation of skip-list. 13 // @field head A sentinel node. 14 // The head.indices[0].succ is the first data node of skip-list. 15 // From head.indices[1], all of them are cache used to implement binary search. 16 // @field tail A sentinel node. Points the skip-list tail node. 17 type xComSkl[K infra.OrderedKey, V any] struct { 18 vcmp SklValComparator[V] // value comparator 19 rand SklRand 20 head *xComSklNode[K, V] 21 tail *xComSklNode[K, V] 22 nodeLen int64 // skip-list's node count. 23 indexCount uint64 // skip-list's index count. 24 levels int32 // skip-list's max height value inside the indexCount. 25 isKeyCmpDesc bool 26 } 27 28 // findPredecessor0 is used to find the (succ) first element whose key value equals to target key value. 29 // Preparing for linear probing. O(N) 30 // @return value 1: the pred node 31 // @return value 2: the query traverse path (nodes) 32 func (skl *xComSkl[K, V]) findPredecessor0(key K, aux []*xComSklNode[K, V]) (*xComSklNode[K, V], []*xComSklNode[K, V]) { 33 var forward *xComSklNode[K, V] 34 forward = skl.head 35 for /* vertical */ i := skl.Levels() - 1; i >= 0; i-- { 36 for /* horizontal */ forward.levels()[i] != nil { 37 cur := forward.levels()[i] 38 res := cmp.Compare[K](key, cur.Element().Key()) 39 if /* greater, forward next */ cur != nil && (!skl.isKeyCmpDesc && res > 0) || (skl.isKeyCmpDesc && res < 0) { 40 // Linear probing (forward next) at level 0 most likely. 41 forward = cur 42 } else /* lower or equal, downward to next level */ { 43 break 44 } 45 } 46 if aux != nil { 47 aux[i] = forward 48 } 49 } 50 51 if /* not found */ forward == nil { 52 return nil, aux 53 } 54 55 target := forward.levels()[0] 56 if /* found */ target != nil && key == target.Element().Key() { 57 return forward, aux 58 } 59 return /* not found */ nil, aux 60 } 61 62 // removeNode will reduce the levels. 63 func (skl *xComSkl[K, V]) removeNode(x *xComSklNode[K, V], aux []*xComSklNode[K, V]) { 64 for i := int32(0); i < skl.Levels(); i++ { 65 if aux[i].levels()[i] == x { 66 aux[i].levels()[i] = x.levels()[i] 67 } 68 } 69 if /* unlink */ next := x.levels()[0]; next != nil { 70 next.setBackward(x.backward()) 71 } else { 72 skl.tail = x.backward() 73 } 74 atomic.AddUint64(&skl.indexCount, ^uint64(len(x.indices)-1)) 75 for /* reduce levels */ skl.Levels() > 1 && skl.head.levels()[skl.Levels()-1] == nil { 76 atomic.AddInt32(&skl.levels, -1) 77 } 78 atomic.AddInt64(&skl.nodeLen, -1) 79 } 80 81 // Classic Skip-List basic APIs 82 83 func (skl *xComSkl[K, V]) Len() int64 { 84 return atomic.LoadInt64(&skl.nodeLen) 85 } 86 87 func (skl *xComSkl[K, V]) IndexCount() uint64 { 88 return atomic.LoadUint64(&skl.indexCount) 89 } 90 91 func (skl *xComSkl[K, V]) Levels() int32 { 92 return atomic.LoadInt32(&skl.levels) 93 } 94 95 func (skl *xComSkl[K, V]) Insert(key K, val V, ifNotPresent ...bool) error { 96 if skl.Len() >= sklMaxSize { 97 return infra.WrapErrorStack(ErrXSklIsFull) 98 } 99 100 var ( 101 pred = skl.head 102 aux = make([]*xComSklNode[K, V], sklMaxLevel) 103 ) 104 105 if len(ifNotPresent) <= 0 { 106 ifNotPresent = insertReplaceDisabled 107 } 108 109 for /* vertical */ i := atomic.LoadInt32(&skl.levels) - 1; i >= 0; i-- { 110 for /* horizontal */ pred.levels()[i] != nil { 111 cur := pred.levels()[i] 112 res := func() int64 { 113 curKey := cur.Element().Key() 114 _res := cmp.Compare[K](key, curKey) 115 if (!skl.isKeyCmpDesc && _res > 0) || (skl.isKeyCmpDesc && _res < 0) { 116 return +1 117 } else if _res == 0 { 118 return 0 119 } 120 return -1 121 }() 122 if /* next insert position */ res > 0 || (res == 0 && skl.vcmp(val, cur.Element().Val()) > 0) { 123 pred = cur 124 } else /* replace */ if res == 0 && skl.vcmp(val, cur.Element().Val()) == 0 { 125 if /* disabled */ ifNotPresent[0] { 126 return infra.WrapErrorStack(ErrXSklDisabledValReplace) 127 128 } 129 cur.element = &xSklElement[K, V]{ 130 key: key, 131 val: val, 132 } 133 return nil 134 } else { 135 break 136 } 137 } 138 // 1. (key duplicated) If new element hash is lower than current node's (do pre-append to current node) 139 // 2. (key duplicated) If new element hash is greater than current node's (do append next to current node) 140 // 3. (key duplicated) If new element hash equals to current node's (replace an element, because the hash 141 // value and element are not strongly correlated) 142 // 4. (new key) If a new element does not exist, (do append next to the current node) 143 aux[i] = pred 144 } 145 146 // Each duplicated key element may contain its cache levels. 147 // It means that duplicated key elements query through the cache (O(logN)) 148 // But duplicated elements query (linear probe) will be degraded into O(N) 149 lvl := skl.rand(sklMaxLevel, skl.Len()) 150 if lvl > skl.Levels() { 151 for i := skl.Levels(); i < lvl; i++ { 152 // Update the whole traverse path, from top to bottom. 153 aux[i] = skl.head // avoid nil pointer 154 } 155 atomic.StoreInt32(&skl.levels, lvl) 156 } 157 atomic.AddUint64(&skl.indexCount, uint64(lvl)) 158 newNode := genXComSklNode[K, V](key, val, lvl) 159 for i := int32(0); i < lvl; i++ { 160 next := aux[i].levels()[i] 161 newNode.levels()[i] = next 162 aux[i].levels()[i] = newNode 163 } 164 if aux[0] == skl.head { 165 newNode.setBackward(nil) 166 } else { 167 newNode.setBackward(aux[0]) 168 } 169 if newNode.levels()[0] == nil { 170 skl.tail = newNode 171 } else { 172 newNode.levels()[0].setBackward(newNode) 173 } 174 atomic.AddInt64(&skl.nodeLen, 1) 175 return nil 176 } 177 178 func (skl *xComSkl[K, V]) LoadFirst(key K) (SklElement[K, V], error) { 179 if skl.Len() <= 0 { 180 return nil, infra.WrapErrorStack(ErrXSklIsEmpty) 181 } 182 183 e, _ := skl.findPredecessor0(key, nil) 184 if e.levels() == nil { 185 return nil, infra.WrapErrorStack(ErrXSklNotFound) 186 } 187 return e.levels()[0].Element(), nil 188 } 189 190 func (skl *xComSkl[K, V]) RemoveFirst(key K) (SklElement[K, V], error) { 191 if skl.Len() <= 0 { 192 return nil, infra.WrapErrorStack(ErrXSklIsEmpty) 193 } 194 195 aux := make([]*xComSklNode[K, V], sklMaxLevel) 196 pred, aux := skl.findPredecessor0(key, aux[:]) 197 if pred == nil { 198 return nil, infra.WrapErrorStack(ErrXSklNotFound) 199 } 200 201 target := pred.levels()[0] 202 if target != nil && key == target.Element().Key() { 203 skl.removeNode(target, aux) 204 return target.Element(), nil 205 } 206 return nil, infra.WrapErrorStack(ErrXSklNotFound) 207 } 208 209 func (skl *xComSkl[K, V]) Foreach(action func(i int64, item SklIterationItem[K, V]) bool) { 210 if skl.Len() <= 0 { 211 return 212 } 213 214 var ( 215 x *xComSklNode[K, V] 216 i int64 217 item = &xSklIter[K, V]{} 218 ) 219 x = skl.head.levels()[0] 220 for x != nil { 221 next := x.levels()[0] 222 item.keyFn = x.element.Key 223 item.valFn = x.element.Val 224 item.nodeLevelFn = func() uint32 { 225 return uint32(len(x.levels())) 226 } 227 item.nodeItemCountFn = func() int64 { 228 return 1 229 } 230 if !action(i, item) { 231 break 232 } 233 i++ 234 x = next 235 } 236 } 237 238 func (skl *xComSkl[K, V]) PeekHead() SklElement[K, V] { 239 target := skl.head 240 if target == nil || skl.Len() <= 0 { 241 return nil 242 } 243 if target = target.levels()[0]; target == nil { 244 return nil 245 } 246 return target.Element() 247 } 248 249 func (skl *xComSkl[K, V]) PopHead() (element SklElement[K, V], err error) { 250 target := skl.head 251 if skl.Len() <= 0 || target == nil { 252 return nil, infra.WrapErrorStack(ErrXSklIsEmpty) 253 } 254 if target = target.levels()[0]; target == nil { 255 return nil, infra.WrapErrorStack(ErrXSklIsEmpty) 256 } 257 element = target.Element() 258 return skl.RemoveFirst(element.Key()) 259 } 260 261 // Duplicated element Skip-List basic APIs 262 263 func (skl *xComSkl[K, V]) LoadIfMatch(key K, matcher func(that V) bool) ([]SklElement[K, V], error) { 264 if skl.Len() <= 0 { 265 return nil, infra.WrapErrorStack(ErrXSklIsEmpty) 266 } 267 268 aux := make([]*xComSklNode[K, V], sklMaxLevel) 269 pred, _ := skl.findPredecessor0(key, aux) 270 if pred == nil { 271 return nil, infra.WrapErrorStack(ErrXSklNotFound) 272 } 273 274 elements := make([]SklElement[K, V], 0, 16) 275 for cur := pred.levels()[0]; cur != nil && key == cur.Element().Key(); cur = cur.levels()[0] { 276 if matcher(cur.Element().Val()) { 277 elements = append(elements, cur.Element()) 278 } 279 } 280 return elements, nil 281 } 282 283 func (skl *xComSkl[K, V]) LoadAll(key K) ([]SklElement[K, V], error) { 284 if skl.Len() <= 0 { 285 return nil, infra.WrapErrorStack(ErrXSklIsEmpty) 286 } 287 288 pred, _ := skl.findPredecessor0(key, nil) 289 if pred == nil { 290 return nil, infra.WrapErrorStack(ErrXSklNotFound) 291 } 292 293 elements := make([]SklElement[K, V], 0, 16) 294 for cur := pred.levels()[0]; cur != nil && key == cur.Element().Key(); cur = cur.levels()[0] { 295 elements = append(elements, cur.Element()) 296 } 297 return elements, nil 298 } 299 300 func (skl *xComSkl[K, V]) RemoveIfMatch(key K, matcher func(that V) bool) ([]SklElement[K, V], error) { 301 if skl.Len() <= 0 { 302 return nil, infra.WrapErrorStack(ErrXSklIsEmpty) 303 } 304 305 aux := make([]*xComSklNode[K, V], sklMaxLevel) 306 pred, aux := skl.findPredecessor0(key, aux) 307 if pred == nil { 308 return nil, infra.WrapErrorStack(ErrXSklNotFound) 309 } 310 311 elements := make([]SklElement[K, V], 0, 16) 312 for cur := pred.levels()[0]; cur != nil && key == cur.Element().Key(); { 313 if matcher(cur.Element().Val()) { 314 skl.removeNode(cur, aux) 315 elements = append(elements, cur.Element()) 316 next := cur.levels()[0] 317 cur.Free() 318 cur = next 319 } else { 320 // Merge the traverse path. 321 for i := 0; i < len(cur.levels()); i++ { 322 aux[i] = cur 323 } 324 cur = cur.levels()[0] 325 } 326 } 327 return elements, nil 328 } 329 330 func (skl *xComSkl[K, V]) RemoveAll(key K) ([]SklElement[K, V], error) { 331 if skl.Len() <= 0 { 332 return nil, infra.WrapErrorStack(ErrXSklIsEmpty) 333 } 334 335 aux := make([]*xComSklNode[K, V], sklMaxLevel) 336 pred, aux := skl.findPredecessor0(key, aux) 337 if pred == nil { 338 return nil, infra.WrapErrorStack(ErrXSklNotFound) 339 } 340 341 elements := make([]SklElement[K, V], 0, 16) 342 for cur := pred.levels()[0]; cur != nil && key == cur.Element().Key(); { 343 skl.removeNode(cur, aux) 344 elements = append(elements, cur.Element()) 345 free := cur 346 cur = cur.levels()[0] 347 free.Free() 348 } 349 return elements, nil 350 } 351 352 func (skl *xComSkl[K, V]) Release() { 353 var ( 354 x, next *xComSklNode[K, V] 355 idx int 356 ) 357 x = skl.head.levels()[0] 358 for x != nil { 359 next = x.levels()[0] 360 x.Free() 361 x = next 362 } 363 for idx = 0; idx < sklMaxLevel; idx++ { 364 skl.head.levels()[idx] = nil 365 } 366 skl.tail = nil 367 }