github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/list/x_skl.go (about) 1 package list 2 3 import ( 4 "errors" 5 "fmt" 6 "sync" 7 8 "go.uber.org/multierr" 9 10 "github.com/benz9527/xboot/lib/id" 11 "github.com/benz9527/xboot/lib/infra" 12 ) 13 14 // References: 15 // https://people.csail.mit.edu/shanir/publications/DCAS.pdf 16 // https://www.cl.cam.ac.uk/teaching/0506/Algorithms/skiplists.pdf 17 // https://people.csail.mit.edu/shanir/publications/LazySkipList.pdf 18 // 19 // github: 20 // classic: https://github.com/antirez/disque/blob/master/src/skiplist.h 21 // classic: https://github.com/antirez/disque/blob/master/src/skiplist.c 22 // zskiplist: https://github1s.com/redis/redis/blob/unstable/src/t_zset.c 23 // https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java 24 // https://github.com/zhangyunhao116/skipmap 25 // https://github.com/liyue201/gostl 26 // https://github.com/chen3feng/stl4go 27 // https://github.com/slclub/skiplist/blob/master/skipList.go 28 // https://github.com/andy-kimball/arenaskl 29 // https://github.com/dgraph-io/badger/tree/master/skl 30 // https://github.com/BazookaMusic/goskiplist/blob/master/skiplist.go 31 // https://github.com/boltdb/bolt/blob/master/freelist.go 32 // https://github.com/xuezhaokun/150-algorithm/tree/master 33 // 34 // test: 35 // https://github.com/chen3feng/skiplist-survey 36 // 37 // 38 // Head nodes Index nodes 39 // +-+ right +-+ +-+ 40 // |2|---------------->| |--------------------->| |->null 41 // +-+ +-+ +-+ 42 // | down | | 43 // v v v 44 // +-+ +-+ +-+ +-+ +-+ +-+ 45 // |1|----------->| |->| |------>| |----------->| |------>| |->null 46 // +-+ +-+ +-+ +-+ +-+ +-+ 47 // v | | | | | 48 // Nodes next v v v v v 49 // +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ 50 // | |->|A|->|B|->|C|->|D|->|E|->|F|->|G|->|H|->|I|->|J|->|K|->null 51 // +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ 52 53 const ( 54 sklMaxLevel = 32 // level 0 is the data node level. 55 sklMaxSize = 1<<(sklMaxLevel-1) - 1 // 2^31 - 1 elements 56 sklProbability = 0.25 // P = 1/4, a skip list node element has 1/4 probability to have a level 57 ) 58 59 type sklError string 60 61 func (err sklError) Error() string { 62 return string(err) 63 } 64 65 const ( 66 ErrXSklNotFound = sklError("[x-skl] key or value not found") 67 ErrXSklDisabledValReplace = sklError("[x-skl] value replace is disabled") 68 ErrXSklConcRWLoadFailed = sklError("[x-skl] concurrent read-write causes load failed") 69 ErrXSklConcRWLoadEmpty = sklError("[x-skl] concurrent read-write causes load empty") 70 ErrXSklConcRemoving = sklError("[x-skl] concurrent removing") 71 ErrXSklConcRemoveTryLock = sklError("[x-skl] concurrent remove acquires segmented lock failed") 72 ErrXSklUnknownReason = sklError("[x-skl] unknown reason error") 73 ErrXSklUnknownType = sklError("[x-skl] unknown skip list type") 74 ErrXSklIsFull = sklError("[x-skl] is full") 75 ErrXSklIsEmpty = sklError("[x-skl] is empty") 76 errXSklRbtreeRedViolation = sklError("[x-skl] red-black tree violation") 77 errXSklRbtreeBlackViolation = sklError("[x-skl] red-black tree violation") 78 errSklOptionWrongTypeApply = sklError("[skl-option] init with wrong type") 79 errSklOptionHasBeenEnabled = sklError("[skl-option] it has been enabled or set already") 80 errSklOptionEmptySettingVal = sklError("[skl-option] empty setting value") 81 ) 82 83 type SklType uint8 84 85 const ( 86 // XComSkl is the classic skip list. 87 // It does not support duplicate keys and values. 88 // It is not thread-safe. 89 XComSkl SklType = iota 90 // XConcSkl is the concurrent skip list. 91 // It supports duplicate keys and values. 92 XConcSkl 93 ) 94 95 type sklOptions[K infra.OrderedKey, V any] struct { 96 valComparator SklValComparator[V] 97 randLevelGen SklRand 98 comRWMutex *sync.RWMutex 99 concOptimisticLockVerGen id.UUIDGen 100 concDataNodeMode *xNodeMode 101 sklType SklType 102 isConcRbtreeBorrowSucc bool 103 keyCmpDesc bool 104 } 105 106 type SklOption[K infra.OrderedKey, V any] func(*sklOptions[K, V]) error 107 108 func WithSklKeyCmpDesc[K infra.OrderedKey, V any]() SklOption[K, V] { 109 return func(opts *sklOptions[K, V]) error { 110 opts.keyCmpDesc = true 111 return nil 112 } 113 } 114 115 func WithSklRandLevelGen[K infra.OrderedKey, V any](gen SklRand) SklOption[K, V] { 116 return func(opts *sklOptions[K, V]) error { 117 if opts.randLevelGen != nil { 118 return fmt.Errorf("[x-skl] random level generator %w", errSklOptionHasBeenEnabled) 119 } else if gen == nil { 120 return fmt.Errorf("[x-skl] random level generator %w", errSklOptionEmptySettingVal) 121 } 122 opts.randLevelGen = gen 123 return nil 124 } 125 } 126 127 func WithXComSklEnableConc[K infra.OrderedKey, V any]() SklOption[K, V] { 128 return func(opts *sklOptions[K, V]) error { 129 if opts.sklType != XComSkl { 130 return fmt.Errorf("[x-com-skl] %w", errSklOptionWrongTypeApply) 131 } else if opts.comRWMutex != nil { 132 return fmt.Errorf("[x-com-skl] concurrent read-write %w", errSklOptionHasBeenEnabled) 133 } 134 opts.comRWMutex = &sync.RWMutex{} 135 return nil 136 } 137 } 138 139 func WithXComSklValComparator[K infra.OrderedKey, V any](cmp SklValComparator[V]) SklOption[K, V] { 140 return func(opts *sklOptions[K, V]) error { 141 if opts.sklType != XComSkl { 142 return fmt.Errorf("[x-com-skl] %w", errSklOptionWrongTypeApply) 143 } else if opts.valComparator != nil { 144 return fmt.Errorf("[x-com-skl] value comparator %w", errSklOptionHasBeenEnabled) 145 } else if cmp == nil { 146 return fmt.Errorf("[x-com-skl] value comparator %w", errSklOptionEmptySettingVal) 147 } 148 opts.valComparator = cmp 149 return nil 150 } 151 } 152 153 func WithXConcSklOptimisticVersionGen[K infra.OrderedKey, V any](verGen id.UUIDGen) SklOption[K, V] { 154 return func(opts *sklOptions[K, V]) error { 155 if opts.sklType != XConcSkl { 156 return fmt.Errorf("[x-conc-skl] %w", errSklOptionWrongTypeApply) 157 } else if opts.concOptimisticLockVerGen != nil { 158 return fmt.Errorf("[x-conc-skl] optimistic lock version generator %w", errSklOptionHasBeenEnabled) 159 } else if verGen == nil { 160 return fmt.Errorf("[x-conc-skl] optimistic lock version generator %w", errSklOptionEmptySettingVal) 161 } 162 opts.concOptimisticLockVerGen = verGen 163 return nil 164 } 165 } 166 167 func WithXConcSklDataNodeUniqueMode[K infra.OrderedKey, V any]() SklOption[K, V] { 168 return func(opts *sklOptions[K, V]) error { 169 if opts.sklType != XConcSkl { 170 return fmt.Errorf("[x-conc-skl] %w", errSklOptionWrongTypeApply) 171 } else if opts.concDataNodeMode != nil && *opts.concDataNodeMode != unique { 172 return fmt.Errorf("[x-conc-skl] unique data node mode set failed, previous mode: %s, %w", *opts.concDataNodeMode, errSklOptionHasBeenEnabled) 173 } else if opts.valComparator != nil { 174 return fmt.Errorf("[x-conc-skl] unique data node mode not support value comparator %w", errSklOptionHasBeenEnabled) 175 } 176 177 mode := unique 178 opts.concDataNodeMode = &mode 179 return nil 180 } 181 } 182 183 func WithXConcSklDataNodeLinkedListMode[K infra.OrderedKey, V any](cmp SklValComparator[V]) SklOption[K, V] { 184 return func(opts *sklOptions[K, V]) error { 185 if opts.sklType != XConcSkl { 186 return fmt.Errorf("[x-conc-skl] %w", errSklOptionWrongTypeApply) 187 } else if opts.concDataNodeMode != nil { 188 return fmt.Errorf("[x-conc-skl] linked list data node mode set failed, previous mode: %s, %w", *opts.concDataNodeMode, errSklOptionHasBeenEnabled) 189 } else if opts.valComparator != nil { 190 return fmt.Errorf("[x-conc-skl] val comparator %w", errSklOptionHasBeenEnabled) 191 } else if cmp == nil { 192 return fmt.Errorf("[x-conc-skl] val comparator%w", errSklOptionEmptySettingVal) 193 } 194 195 mode := linkedList 196 opts.concDataNodeMode = &mode 197 opts.valComparator = cmp 198 return nil 199 } 200 } 201 202 func WithXConcSklDataNodeRbtreeMode[K infra.OrderedKey, V any](cmp SklValComparator[V], borrowSucc ...bool) SklOption[K, V] { 203 return func(opts *sklOptions[K, V]) error { 204 if opts.sklType != XConcSkl { 205 return fmt.Errorf("[x-conc-skl] %w", errSklOptionWrongTypeApply) 206 } else if opts.concDataNodeMode != nil { 207 return fmt.Errorf("[x-conc-skl] rbtree data node mode set failed, previous mode: %s, %w", *opts.concDataNodeMode, errSklOptionHasBeenEnabled) 208 } else if opts.valComparator != nil { 209 return fmt.Errorf("[x-conc-skl] value comparator %w", errSklOptionHasBeenEnabled) 210 } else if cmp == nil { 211 return fmt.Errorf("[x-conc-skl] value comparator %w", errSklOptionEmptySettingVal) 212 } 213 214 opts.isConcRbtreeBorrowSucc = len(borrowSucc) > 0 && borrowSucc[0] 215 mode := rbtree 216 opts.concDataNodeMode = &mode 217 opts.valComparator = cmp 218 return nil 219 } 220 } 221 222 var _ SkipList[uint8, struct{}] = (*sklDelegator[uint8, struct{}])(nil) 223 224 // sklDelegator is the skip list delegator. 225 // It does not support duplicate keys and values. 226 // Concurrent read-write mode is supported if enabled. 227 type sklDelegator[K infra.OrderedKey, V any] struct { 228 rwmu *sync.RWMutex 229 impl SkipList[K, V] 230 } 231 232 func (skl *sklDelegator[K, V]) Len() int64 { return skl.impl.Len() } 233 func (skl *sklDelegator[K, V]) Levels() int32 { return skl.impl.Levels() } 234 func (skl *sklDelegator[K, V]) IndexCount() uint64 { return skl.impl.IndexCount() } 235 func (skl *sklDelegator[K, V]) Insert(key K, val V, ifNotPresent ...bool) error { 236 if skl.rwmu != nil { 237 skl.rwmu.Lock() 238 defer skl.rwmu.Unlock() 239 } 240 return skl.impl.Insert(key, val, ifNotPresent...) 241 } 242 243 func (skl *sklDelegator[K, V]) Foreach(action func(int64, SklIterationItem[K, V]) bool) { 244 if skl.rwmu != nil { 245 skl.rwmu.RLock() 246 defer skl.rwmu.RUnlock() 247 } 248 skl.impl.Foreach(action) 249 } 250 251 func (skl *sklDelegator[K, V]) LoadFirst(key K) (SklElement[K, V], error) { 252 if skl.rwmu != nil { 253 skl.rwmu.RLock() 254 defer skl.rwmu.RUnlock() 255 } 256 return skl.impl.LoadFirst(key) 257 } 258 func (skl *sklDelegator[K, V]) PeekHead() SklElement[K, V] { return skl.impl.PeekHead() } 259 func (skl *sklDelegator[K, V]) PopHead() (SklElement[K, V], error) { 260 if skl.rwmu != nil { 261 skl.rwmu.Lock() 262 defer skl.rwmu.Unlock() 263 } 264 return skl.impl.PopHead() 265 } 266 267 func (skl *sklDelegator[K, V]) RemoveFirst(key K) (SklElement[K, V], error) { 268 if skl.rwmu != nil { 269 skl.rwmu.Lock() 270 defer skl.rwmu.Unlock() 271 } 272 return skl.impl.RemoveFirst(key) 273 } 274 275 func NewSkl[K infra.OrderedKey, V any](typ SklType, opts ...SklOption[K, V]) (SkipList[K, V], error) { 276 sklOpts := &sklOptions[K, V]{ 277 sklType: typ, 278 } 279 280 var err error 281 for _, o := range opts { 282 err = multierr.Append(err, o(sklOpts)) 283 } 284 if err != nil { 285 return nil, err 286 } 287 288 if sklOpts.randLevelGen == nil { 289 sklOpts.randLevelGen = randomLevelV2 290 } 291 292 switch typ { 293 case XComSkl: 294 if sklOpts.valComparator != nil { 295 return nil, errors.New("[x-com-skl] init the unique data node mode but value comparator is set") 296 } 297 case XConcSkl: 298 if sklOpts.concDataNodeMode == nil { 299 mode := unique 300 sklOpts.concDataNodeMode = &mode 301 } 302 if *sklOpts.concDataNodeMode != unique { 303 return nil, fmt.Errorf("[x-conc-skl] init with the wrong mode: %s", *sklOpts.concDataNodeMode) 304 } 305 if sklOpts.valComparator != nil { 306 return nil, errors.New("[x-conc-skl] init the unique data node mode but value comparator is set") 307 } 308 if sklOpts.concOptimisticLockVerGen == nil { 309 gen, _ := id.MonotonicNonZeroID() // fallback to monotonic non-zero id 310 sklOpts.concOptimisticLockVerGen = gen 311 } 312 if sklOpts.concDataNodeMode == nil { 313 mode := unique // fallback to unique 314 sklOpts.concDataNodeMode = &mode 315 } 316 default: 317 return nil, ErrXSklUnknownType 318 } 319 320 impl, err := sklFactory(sklOpts) 321 if err != nil { 322 return nil, err 323 } 324 d := &sklDelegator[K, V]{ 325 impl: impl, 326 } 327 if typ == XComSkl && sklOpts.comRWMutex != nil { 328 d.rwmu = sklOpts.comRWMutex 329 } 330 return d, nil 331 } 332 333 var _ XSkipList[uint8, struct{}] = (*xSklDelegator[uint8, struct{}])(nil) 334 335 // xSklDelegator is the skip list delegator. 336 // It supports duplicate keys and values. 337 // Concurrent read-write mode is supported if enabled. 338 type xSklDelegator[K infra.OrderedKey, V any] struct { 339 rwmu *sync.RWMutex 340 impl XSkipList[K, V] 341 } 342 343 func (skl *xSklDelegator[K, V]) Len() int64 { return skl.impl.Len() } 344 func (skl *xSklDelegator[K, V]) Levels() int32 { return skl.impl.Levels() } 345 func (skl *xSklDelegator[K, V]) IndexCount() uint64 { return skl.impl.IndexCount() } 346 func (skl *xSklDelegator[K, V]) Insert(key K, val V, ifNotPresent ...bool) error { 347 if skl.rwmu != nil { 348 skl.rwmu.Lock() 349 defer skl.rwmu.Unlock() 350 } 351 return skl.impl.Insert(key, val, ifNotPresent...) 352 } 353 354 func (skl *xSklDelegator[K, V]) Foreach(action func(int64, SklIterationItem[K, V]) bool) { 355 if skl.rwmu != nil { 356 skl.rwmu.RLock() 357 defer skl.rwmu.RUnlock() 358 } 359 skl.impl.Foreach(action) 360 } 361 362 func (skl *xSklDelegator[K, V]) LoadFirst(key K) (SklElement[K, V], error) { 363 if skl.rwmu != nil { 364 skl.rwmu.RLock() 365 defer skl.rwmu.RUnlock() 366 } 367 return skl.impl.LoadFirst(key) 368 } 369 func (skl *xSklDelegator[K, V]) PeekHead() SklElement[K, V] { return skl.impl.PeekHead() } 370 func (skl *xSklDelegator[K, V]) PopHead() (SklElement[K, V], error) { 371 if skl.rwmu != nil { 372 skl.rwmu.Lock() 373 defer skl.rwmu.Unlock() 374 } 375 return skl.impl.PopHead() 376 } 377 378 func (skl *xSklDelegator[K, V]) RemoveFirst(key K) (SklElement[K, V], error) { 379 if skl.rwmu != nil { 380 skl.rwmu.Lock() 381 defer skl.rwmu.Unlock() 382 } 383 return skl.impl.RemoveFirst(key) 384 } 385 386 func (skl *xSklDelegator[K, V]) LoadAll(key K) ([]SklElement[K, V], error) { 387 if skl.rwmu != nil { 388 skl.rwmu.RLock() 389 defer skl.rwmu.RUnlock() 390 } 391 return skl.impl.LoadAll(key) 392 } 393 394 func (skl *xSklDelegator[K, V]) LoadIfMatch(key K, matcher func(V) bool) ([]SklElement[K, V], error) { 395 if skl.rwmu != nil { 396 skl.rwmu.RLock() 397 defer skl.rwmu.RUnlock() 398 } 399 return skl.impl.LoadIfMatch(key, matcher) 400 } 401 402 func (skl *xSklDelegator[K, V]) RemoveAll(key K) ([]SklElement[K, V], error) { 403 if skl.rwmu != nil { 404 skl.rwmu.Lock() 405 defer skl.rwmu.Unlock() 406 } 407 return skl.impl.RemoveAll(key) 408 } 409 410 func (skl *xSklDelegator[K, V]) RemoveIfMatch(key K, matcher func(V) bool) ([]SklElement[K, V], error) { 411 if skl.rwmu != nil { 412 skl.rwmu.Lock() 413 defer skl.rwmu.Unlock() 414 } 415 return skl.impl.RemoveIfMatch(key, matcher) 416 } 417 418 func NewXSkl[K infra.OrderedKey, V any](typ SklType, opts ...SklOption[K, V]) (XSkipList[K, V], error) { 419 sklOpts := &sklOptions[K, V]{ 420 sklType: typ, 421 } 422 var err error 423 for _, o := range opts { 424 err = multierr.Append(err, o(sklOpts)) 425 } 426 if err != nil { 427 return nil, err 428 } 429 430 if sklOpts.randLevelGen == nil { 431 sklOpts.randLevelGen = randomLevelV2 432 } 433 434 switch typ { 435 case XComSkl: 436 if sklOpts.valComparator == nil { 437 return nil, errors.New("[x-skl] x-com-skl non-unique mode, the value comparator must be set") 438 } 439 case XConcSkl: 440 if sklOpts.concDataNodeMode == nil { 441 mode := rbtree // fallback to rbtree mode 442 sklOpts.concDataNodeMode = &mode 443 } 444 if sklOpts.concDataNodeMode != nil && *sklOpts.concDataNodeMode == unique { 445 return nil, fmt.Errorf("[x-skl] x-conc-skl init with the wrong mode: %s", unique) 446 } 447 if sklOpts.valComparator == nil { 448 return nil, errors.New("[x-skl] x-conc-skl non-unique data node mode, the value comparator must be set") 449 } 450 if sklOpts.concOptimisticLockVerGen == nil { 451 gen, _ := id.MonotonicNonZeroID() // fallback to monotonic non-zero id 452 sklOpts.concOptimisticLockVerGen = gen 453 } 454 default: 455 return nil, ErrXSklUnknownType 456 } 457 458 impl, err := sklFactory(sklOpts) 459 if err != nil { 460 return nil, err 461 } 462 d := &xSklDelegator[K, V]{ 463 impl: impl, 464 } 465 if typ == XComSkl && sklOpts.comRWMutex != nil { 466 d.rwmu = sklOpts.comRWMutex 467 } 468 return d, nil 469 } 470 471 func sklFactory[K infra.OrderedKey, V any](opts *sklOptions[K, V]) (XSkipList[K, V], error) { 472 var impl XSkipList[K, V] 473 switch opts.sklType { 474 case XComSkl: 475 skl := &xComSkl[K, V]{ 476 // Start from 1 means the x-com-skl cache levels at least a one level is fixed 477 levels: 1, 478 nodeLen: 0, 479 vcmp: opts.valComparator, 480 rand: opts.randLevelGen, 481 isKeyCmpDesc: opts.keyCmpDesc, 482 } 483 skl.head = genXComSklNode[K, V](*new(K), *new(V), sklMaxLevel) 484 skl.head.setBackward(nil) 485 skl.tail = nil 486 impl = skl 487 case XConcSkl: 488 skl := &xConcSkl[K, V]{ 489 // Start from 1 means the x-conc-skl cache levels at least a one level is fixed 490 levels: 1, 491 nodeLen: 0, 492 head: newXConcSklHead[K, V](), 493 vcmp: opts.valComparator, 494 optVer: opts.concOptimisticLockVerGen, 495 rand: opts.randLevelGen, 496 flags: 0, 497 } 498 if opts.keyCmpDesc { 499 skl.flags = set(skl.flags, xConcSklKeyCmpFlagBit) 500 } 501 skl.flags = setBitsAs(skl.flags, xConcSklXNodeModeFlagBits, uint32(*opts.concDataNodeMode)) 502 if *opts.concDataNodeMode == rbtree && opts.isConcRbtreeBorrowSucc { 503 skl.flags = set(skl.flags, xConcSklRbtreeRmBorrowFlagBit) 504 } 505 impl = skl 506 default: 507 return nil, errors.New("[x-skl] unknown skip list type") 508 } 509 return impl, nil 510 }