github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/list/x_conc_skl_node.go (about) 1 package list 2 3 import ( 4 "runtime" 5 "sync/atomic" 6 "unsafe" 7 8 "github.com/benz9527/xboot/lib/infra" 9 ) 10 11 type color bool 12 13 const ( 14 red color = true 15 black color = false 16 ) 17 18 // embedded data-structure 19 // singly linked-list and rbtree 20 // @field vptr: In Uber go guid, it is not to store a pointer for interface type. 21 // But in this case, we don't know whether the V (any) is an interface type. 22 // And it is easy way for us to debug the value. 23 type xNode[V any] struct { 24 // parent It is easy for us to backward to access upper level node info. 25 parent *xNode[V] // Linked-list & rbtree 26 left *xNode[V] // rbtree only 27 right *xNode[V] // rbtree only 28 vptr *V // value pointer. Dangerous! 29 color color 30 } 31 32 func (n *xNode[V]) linkedListNext() *xNode[V] { 33 return n.parent 34 } 35 36 /* rbtree helper methods */ 37 38 func (n *xNode[V]) isRed() bool { 39 return !n.isNilLeaf() && n.color == red 40 } 41 42 func (n *xNode[V]) isBlack() bool { 43 return n.isNilLeaf() || n.color == black 44 } 45 46 func (n *xNode[V]) isNilLeaf() bool { 47 return n == nil || (n.vptr == nil && n.parent == nil && n.left == nil && n.right == nil) 48 } 49 50 func (n *xNode[V]) isLeaf() bool { 51 return n != nil && n.parent != nil && n.left.isNilLeaf() && n.right.isNilLeaf() 52 } 53 54 func (n *xNode[V]) isRoot() bool { 55 return n != nil && n.parent == nil 56 } 57 58 func (n *xNode[V]) blackDepthTo(root *xNode[V]) int { 59 depth := 0 60 for aux := n; aux != root; aux = aux.parent { 61 if aux.isBlack() { 62 depth++ 63 } 64 } 65 return depth 66 } 67 68 type rbDirection int8 69 70 const ( 71 left rbDirection = -1 + iota 72 root 73 right 74 ) 75 76 func (n *xNode[V]) direction() rbDirection { 77 if n.isNilLeaf() { 78 // impossible run to here 79 panic( /* debug assertion */ "[x-conc-skl] rbtree nil leaf node without direction") 80 } 81 82 if n.isRoot() { 83 return root 84 } 85 if n == n.parent.left { 86 return left 87 } 88 return right 89 } 90 91 func (n *xNode[V]) sibling() *xNode[V] { 92 dir := n.direction() 93 switch dir { 94 case left: 95 return n.parent.right 96 case right: 97 return n.parent.left 98 default: 99 100 } 101 return nil 102 } 103 104 func (n *xNode[V]) hasSibling() bool { 105 return !n.isRoot() && n.sibling() != nil 106 } 107 108 func (n *xNode[V]) uncle() *xNode[V] { 109 return n.parent.sibling() 110 } 111 112 func (n *xNode[V]) hasUncle() bool { 113 return !n.isRoot() && n.parent.hasSibling() 114 } 115 116 func (n *xNode[V]) grandpa() *xNode[V] { 117 return n.parent.parent 118 } 119 120 func (n *xNode[V]) hasGrandpa() bool { 121 return !n.isRoot() && n.parent.parent != nil 122 } 123 124 func (n *xNode[V]) fixLink() { 125 if n.left != nil { 126 n.left.parent = n 127 } 128 if n.right != nil { 129 n.right.parent = n 130 } 131 } 132 133 func (n *xNode[V]) minimum() *xNode[V] { 134 aux := n 135 for ; aux != nil && aux.left != nil; aux = aux.left { 136 } 137 return aux 138 } 139 140 func (n *xNode[V]) maximum() *xNode[V] { 141 aux := n 142 for ; aux != nil && aux.right != nil; aux = aux.right { 143 } 144 return aux 145 } 146 147 // The pred node of the current node is its previous node in sorted order 148 func (n *xNode[V]) pred() *xNode[V] { 149 x := n 150 if x == nil { 151 return nil 152 } 153 aux := x 154 if aux.left != nil { 155 return aux.left.maximum() 156 } 157 158 aux = x.parent 159 // Backtrack to father node that is the x's pred. 160 for aux != nil && x == aux.left { 161 x = aux 162 aux = aux.parent 163 } 164 return aux 165 } 166 167 // The succ node of the current node is its next node in sorted order. 168 func (n *xNode[V]) succ() *xNode[V] { 169 x := n 170 if x == nil { 171 return nil 172 } 173 174 aux := x 175 if aux.right != nil { 176 return aux.right.minimum() 177 } 178 179 aux = x.parent 180 // Backtrack to father node that is the x's succ. 181 for aux != nil && x == aux.right { 182 x = aux 183 aux = aux.parent 184 } 185 return aux 186 } 187 188 const ( 189 nodeInsertedFlagBit = 1 << iota 190 nodeRemovingFlagBit 191 nodeIsHeadFlagBit 192 nodeIsSetFlagBit /* 0: unique; 1: enable linked-list or rbtree */ 193 nodeSetModeFlagBit /* 0: linked-list; 1: rbtree */ 194 nodeRbRmBorrowFlagBit /* 0: pred; 1: succ */ 195 196 insertFullyLinked = nodeInsertedFlagBit 197 xNodeModeFlagBits = nodeIsSetFlagBit | nodeSetModeFlagBit 198 ) 199 200 type xNodeMode uint8 201 202 const ( 203 unique xNodeMode = 0 204 linkedList xNodeMode = 1 205 rbtree xNodeMode = 3 206 ) 207 208 const ( 209 unlocked = 0 210 ) 211 212 func (mode xNodeMode) String() string { 213 switch mode { 214 case unique: 215 return "unique" 216 case linkedList: 217 return "linked-list" 218 case rbtree: 219 return "rbtree" 220 default: 221 return "unknown" 222 } 223 } 224 225 // If it is unique x-node type store value directly. 226 // Otherwise, it is a sentinel node for linked-list or rbtree. 227 // @field count, the number of duplicate elements. 228 // @field mu, lock-free, spin-lock, optimistic-lock. 229 type xConcSklNode[K infra.OrderedKey, V any] struct { 230 indices []*xConcSklNode[K, V] // size 24, 3 bytes 231 root *xNode[V] // size 8, 1 byte 232 key K // size 8, 1 byte 233 mu uint64 // size 8, 2 byte 234 count int64 // size 8, 1 byte 235 level uint32 // size 4 236 flags uint32 // size 4 237 } 238 239 func (node *xConcSklNode[K, V]) lock(version uint64) { 240 backoff := uint8(1) 241 for !atomic.CompareAndSwapUint64(&node.mu, unlocked, version) { 242 if backoff <= 32 { 243 for i := uint8(0); i < backoff; i++ { 244 infra.ProcYield(5) 245 } 246 } else { 247 runtime.Gosched() 248 } 249 backoff <<= 1 250 } 251 } 252 253 func (node *xConcSklNode[K, V]) tryLock(version uint64) bool { 254 return atomic.CompareAndSwapUint64(&node.mu, unlocked, version) 255 } 256 257 func (node *xConcSklNode[K, V]) unlock(version uint64) bool { 258 return atomic.CompareAndSwapUint64(&node.mu, version, unlocked) 259 } 260 261 func (node *xConcSklNode[K, V]) storeVal(ver uint64, val V, vcmp SklValComparator[V], ifNotPresent ...bool) (isAppend bool, err error) { 262 switch mode := xNodeMode(atomicLoadBits(&node.flags, xNodeModeFlagBits)); mode { 263 case unique: 264 if ifNotPresent[0] { 265 return false, infra.WrapErrorStack(ErrXSklDisabledValReplace) 266 } 267 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&node.root.vptr)), unsafe.Pointer(&val)) 268 case linkedList: 269 // pred 270 node.lock(ver) 271 atomicUnset(&node.flags, nodeInsertedFlagBit) 272 isAppend, err = node.llInsert(val, vcmp, ifNotPresent...) 273 node.unlock(ver) 274 atomicSet(&node.flags, nodeInsertedFlagBit) 275 case rbtree: 276 node.lock(ver) 277 atomicUnset(&node.flags, nodeInsertedFlagBit) 278 isAppend, err = node.rbInsert(val, vcmp) 279 node.unlock(ver) 280 atomicSet(&node.flags, nodeInsertedFlagBit) 281 default: 282 // impossible run to here 283 panic( /* debug assertion */ "[x-conc-skl] unknown x-node type") 284 } 285 return isAppend, infra.WrapErrorStack(err) 286 } 287 288 func (node *xConcSklNode[K, V]) atomicLoadRoot() *xNode[V] { 289 return (*xNode[V])(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&node.root)))) 290 } 291 292 func (node *xConcSklNode[K, V]) loadNextNode(i int32) *xConcSklNode[K, V] { 293 return node.indices[i] 294 } 295 296 func (node *xConcSklNode[K, V]) storeNextNode(i int32, next *xConcSklNode[K, V]) { 297 node.indices[i] = next 298 } 299 300 func (node *xConcSklNode[K, V]) atomicLoadNextNode(i int32) *xConcSklNode[K, V] { 301 return (*xConcSklNode[K, V])(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&node.indices[i])))) 302 } 303 304 func (node *xConcSklNode[K, V]) atomicStoreNextNode(i int32, next *xConcSklNode[K, V]) { 305 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&node.indices[i])), unsafe.Pointer(next)) 306 } 307 308 /* linked-list operation implementation */ 309 310 func (node *xConcSklNode[K, V]) llInsert(val V, vcmp SklValComparator[V], ifNotPresent ...bool) (isAppend bool, err error) { 311 for pred, n := node.root, node.root.linkedListNext(); n != nil; n = n.linkedListNext() { 312 if /* replace */ res := vcmp(val, *n.vptr); res == 0 { 313 if /* disabled */ ifNotPresent[0] { 314 return false, infra.WrapErrorStack(ErrXSklDisabledValReplace) 315 } 316 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&n.vptr)), unsafe.Pointer(&val)) 317 break 318 } else /* append */ if res > 0 { 319 pred = n 320 if next := n.parent; next != nil { 321 continue 322 } 323 x := &xNode[V]{ 324 vptr: &val, 325 parent: n.parent, 326 } 327 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&n.parent)), unsafe.Pointer(x)) 328 atomic.AddInt64(&node.count, 1) 329 isAppend = true 330 break 331 } else /* prepend */ { 332 x := &xNode[V]{ 333 vptr: &val, 334 parent: n, 335 } 336 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&pred.parent)), unsafe.Pointer(x)) 337 atomic.AddInt64(&node.count, 1) 338 isAppend = true 339 break 340 } 341 } 342 return isAppend, nil 343 } 344 345 /* rbtree operation implementation */ 346 347 // References: 348 // https://elixir.bootlin.com/linux/latest/source/lib/rbtree.c 349 // rbtree properties: 350 // https://en.wikipedia.org/wiki/Red%E2%80%93black_tree#Properties 351 // p1. Every node is either red or black. 352 // p2. All NIL nodes are considered black. 353 // p3. A red node does not have a red child. (red-violation) 354 // p4. Every path from a given node to any of its descendant 355 // NIL nodes goes through the same number of black nodes. (black-violation) 356 // p5. (Optional) The root is black. 357 // (Conclusion) If a node X has exactly one child, it must be a red child, 358 // because if it were black, its NIL descendants would sit at a different 359 // black depth than X's NIL child, violating p4. 360 // So the shortest path nodes are black nodes. Otherwise, 361 // the path must contain red node. 362 // The longest path nodes' number is 2 * shortest path nodes' number. 363 364 /* 365 | | 366 X S 367 / \ leftRotate(X) / \ 368 L S ============> X Sd 369 / \ / \ 370 Sc Sd L Sc 371 */ 372 func (node *xConcSklNode[K, V]) rbLeftRotate(x *xNode[V]) { 373 if x == nil || x.right.isNilLeaf() { 374 // impossible run to here 375 panic( /* debug assertion */ "[x-conc-skl] rbtree left rotate node x is nil or x.right is nil") 376 } 377 378 p, y := x.parent, x.right 379 dir := x.direction() 380 x.right, y.left = y.left, x 381 382 x.fixLink() 383 y.fixLink() 384 385 switch dir { 386 case root: 387 node.root = y 388 case left: 389 p.left = y 390 case right: 391 p.right = y 392 default: 393 // impossible run to here 394 panic( /* debug assertion */ "[x-conc-skl] unknown x-node type") 395 } 396 y.parent = p 397 } 398 399 /* 400 | | 401 X S 402 / \ rightRotate(S) / \ 403 L S <============ X R 404 / \ / \ 405 Sc Sd Sc Sd 406 */ 407 func (node *xConcSklNode[K, V]) rbRightRotate(x *xNode[V]) { 408 if x == nil || x.left.isNilLeaf() { 409 // impossible run to here 410 panic( /* debug assertion */ "[x-conc-skl] rbtree right rotate node x is nil or x.right is nil") 411 } 412 413 p, y := x.parent, x.left 414 dir := x.direction() 415 x.left, y.right = y.right, x 416 417 x.fixLink() 418 y.fixLink() 419 420 switch dir { 421 case root: 422 node.root = y 423 case left: 424 p.left = y 425 case right: 426 p.right = y 427 default: 428 // impossible run to here 429 panic( /* debug assertion */ "[x-conc-skl] unknown x-node type") 430 } 431 y.parent = p 432 } 433 434 // i1: Empty rbtree, insert directly, but root node is painted to black. 435 func (node *xConcSklNode[K, V]) rbInsert(val V, vcmp SklValComparator[V], ifNotPresent ...bool) (isAppend bool, err error) { 436 if /* i1 */ node.root.isNilLeaf() { 437 node.root = &xNode[V]{ 438 vptr: &val, 439 } 440 atomic.AddInt64(&node.count, 1) 441 return true, nil 442 } 443 444 var x, y *xNode[V] = node.root, nil 445 for !x.isNilLeaf() { 446 y = x 447 res := vcmp(val, *x.vptr) 448 if /* equal */ res == 0 { 449 break 450 } else /* less */ if res < 0 { 451 x = x.left 452 } else /* greater */ { 453 x = x.right 454 } 455 } 456 457 if y.isNilLeaf() { 458 // impossible run to here 459 panic( /* debug assertion */ "[x-conc-skl] rbtree insert a new value into nil node") 460 } 461 462 var z *xNode[V] 463 res := vcmp(val, *y.vptr) 464 if /* equal */ res == 0 { 465 if /* disabled */ ifNotPresent[0] { 466 return false, ErrXSklDisabledValReplace 467 } 468 y.vptr = &val 469 return false, nil 470 } else /* less */ if res < 0 { 471 z = &xNode[V]{ 472 vptr: &val, 473 color: red, 474 parent: y, 475 } 476 y.left = z 477 } else /* greater */ { 478 z = &xNode[V]{ 479 vptr: &val, 480 color: red, 481 parent: y, 482 } 483 y.right = z 484 } 485 486 atomic.AddInt64(&node.count, 1) 487 node.rbInsertRebalance(z) 488 return true, nil 489 } 490 491 /* 492 New node X is red by default. 493 494 <X> is a RED node. 495 [X] is a BLACK node (or NIL). 496 {X} is either a RED node or a BLACK node. 497 498 im1: Current node X's parent P is black and P is root, so hold r3 and r4. 499 500 im2: Current node X's parent P is red and P is root, repaint P into black. 501 502 im3: If both the parent P and the uncle U are red, grandpa G is black. 503 (red-violation) 504 After repainted G into red may be still red-violation. 505 Recursive to fix grandpa. 506 507 [G] <G> 508 / \ / \ 509 <P> <U> ====> [P] [U] 510 / / 511 <X> <X> 512 513 im4: The parent P is red but the uncle U is black. (red-violation) 514 X is opposite direction to P. Rotate P to opposite direction. 515 After rotation may be still red-violation. Here must enter im5 to fix. 516 517 [G] [G] 518 / \ rotate(P) / \ 519 <P> [U] ========> <X> [U] 520 \ / 521 <X> <P> 522 523 im5: Handle im4 scenario, current node is the same direction as parent. 524 525 [G] <P> [P] 526 / \ rotate(G) / \ repaint / \ 527 <P> [U] ========> <X> [G] ======> <X> <G> 528 / \ \ 529 <X> [U] [U] 530 */ 531 func (node *xConcSklNode[K, V]) rbInsertRebalance(x *xNode[V]) { 532 for !x.isNilLeaf() { 533 if x.isRoot() { 534 if x.isRed() { 535 x.color = black 536 } 537 return 538 } 539 540 if x.parent.isBlack() { 541 return 542 } 543 544 if x.parent.isRoot() { 545 if /* im1 */ x.parent.isBlack() { 546 return 547 } else /* im2 */ { 548 x.parent.color = black 549 } 550 } 551 552 if /* im3 */ x.hasUncle() && x.uncle().isRed() { 553 x.parent.color = black 554 x.uncle().color = black 555 gp := x.grandpa() 556 gp.color = red 557 x = gp 558 continue 559 } else { 560 if !x.hasUncle() || x.uncle().isBlack() { 561 dir := x.direction() 562 if /* im4 */ dir != x.parent.direction() { 563 p := x.parent 564 switch dir { 565 case left: 566 node.rbRightRotate(p) 567 case right: 568 node.rbLeftRotate(p) 569 default: 570 // impossible run to here 571 panic( /* debug assertion */ "[x-conc-skl] rbtree insert violate (im4)") 572 } 573 x = p // enter im5 to fix 574 } 575 576 switch /* im5 */ dir = x.parent.direction(); dir { 577 case left: 578 node.rbRightRotate(x.grandpa()) 579 case right: 580 node.rbLeftRotate(x.grandpa()) 581 default: 582 // impossible run to here 583 panic( /* debug assertion */ "[x-conc-skl] rbtree insert violate (im5)") 584 } 585 586 x.parent.color = black 587 x.sibling().color = red 588 return 589 } 590 } 591 } 592 } 593 594 /* 595 r1: Only a root node, remove directly. 596 597 r2: Current node X has left and right node. 598 Find node X's pred or succ to replace it to be removed. 599 Swap the value only. 600 Both of pred and succ are nil left and right node. 601 602 Find pred: 603 604 | | 605 X L 606 / \ / \ 607 L .. swap(X, L) X .. 608 | =========> | 609 P P 610 / \ / \ 611 S .. S .. 612 613 Find succ: 614 615 | | 616 X S 617 / \ / \ 618 L .. swap(X, S) L .. 619 | =========> | 620 P P 621 / \ / \ 622 S .. X .. 623 624 r3: (1) Current node X is a red leaf node, remove directly. 625 626 r3: (2) Current node X is a black leaf node, we have to rebalance after remove. 627 (black-violation) 628 629 r4: Current node X is not a leaf node but contains a not nil child node. 630 The child node must be a red node. (See conclusion. Otherwise, black-violation) 631 */ 632 func (node *xConcSklNode[K, V]) rbRemoveNode(z *xNode[V]) (res *xNode[V], err error) { 633 if /* r1 */ atomic.LoadInt64(&node.count) == 1 && z.isRoot() { 634 node.root = nil 635 z.left = nil 636 z.right = nil 637 return z, nil 638 } 639 640 res = &xNode[V]{ 641 vptr: z.vptr, 642 } 643 644 y := z 645 if /* r2 */ !y.left.isNilLeaf() && !y.right.isNilLeaf() { 646 if isSet(node.flags, nodeRbRmBorrowFlagBit) { 647 y = z.succ() // enter r3-r4 648 } else { 649 y = z.pred() // enter r3-r4 650 } 651 // Swap value only. 652 z.vptr = y.vptr 653 } 654 655 if /* r3 */ y.isLeaf() { 656 if /* r3 (1) */ y.isRed() { 657 switch dir := y.direction(); dir { 658 case left: 659 y.parent.left = nil 660 case right: 661 y.parent.right = nil 662 default: 663 // impossible run to here 664 panic( /* debug assertion */ "[x-conc-skl] rbtree x-node y should be a leaf node, violate (r3-1)") 665 } 666 return res, nil 667 } else /* r3 (2) */ { 668 node.rbRemoveRebalance(y) 669 } 670 } else /* r4 */ { 671 var replace *xNode[V] 672 if !y.right.isNilLeaf() { 673 replace = y.right 674 } else if !y.left.isNilLeaf() { 675 replace = y.left 676 } 677 678 if replace == nil { 679 // impossible run to here 680 panic( /* debug assertion */ "[x-conc-skl] rbtree remove a leaf node without child, violate (r4)") 681 } 682 683 switch dir := y.direction(); dir { 684 case root: 685 node.root = replace 686 node.root.parent = nil 687 case left: 688 y.parent.left = replace 689 replace.parent = y.parent 690 case right: 691 y.parent.right = replace 692 replace.parent = y.parent 693 default: 694 // impossible run to here 695 panic( /* debug assertion */ "[x-conc-skl] rbtree impossible run to here") 696 } 697 698 if y.isBlack() { 699 if replace.isRed() { 700 replace.color = black 701 } else { 702 node.rbRemoveRebalance(replace) 703 } 704 } 705 } 706 707 // Unlink node 708 if !y.isRoot() && y == y.parent.left { 709 y.parent.left = nil 710 } else if !y.isRoot() && y == y.parent.right { 711 y.parent.right = nil 712 } 713 y.parent = nil 714 y.left = nil 715 y.right = nil 716 717 return res, nil 718 } 719 720 func (node *xConcSklNode[K, V]) rbRemove(val V, vcmp SklValComparator[V]) (*xNode[V], error) { 721 if atomic.LoadInt64(&node.count) <= 0 { 722 return nil, infra.WrapErrorStack(ErrXSklNotFound) 723 } 724 z := node.rbSearch(node.root, func(vn *xNode[V]) int64 { 725 return vcmp(val, *vn.vptr) 726 }) 727 if z == nil { 728 return nil, infra.WrapErrorStack(ErrXSklNotFound) 729 } 730 defer func() { 731 atomic.AddInt64(&node.count, -1) 732 }() 733 734 return node.rbRemoveNode(z) 735 } 736 737 func (node *xConcSklNode[K, V]) rbRemoveMin() (*xNode[V], error) { 738 if atomic.LoadInt64(&node.count) <= 0 { 739 return nil, infra.WrapErrorStack(ErrXSklNotFound) 740 } 741 _min := node.root.minimum() 742 if _min.isNilLeaf() { 743 return nil, infra.WrapErrorStack(ErrXSklNotFound) 744 } 745 defer func() { 746 atomic.AddInt64(&node.count, -1) 747 }() 748 return node.rbRemoveNode(_min) 749 } 750 751 /* 752 <X> is a RED node. 753 [X] is a BLACK node (or NIL). 754 {X} is either a RED node or a BLACK node. 755 756 Sc is the same direction to X and it X's sibling's child node. 757 Sd is the opposite direction to X and it X's sibling's child node. 758 759 rm1: Current node X's sibling S is red, so the parent P, nephew node Sc and Sd 760 must be black. (Otherwise, red-violation) 761 (1) X is left node of P, left rotate P 762 (2) X is right node of P, right rotate P. 763 (3) repaint S into black, P into red. 764 765 [P] <S> [S] 766 / \ l-rotate(P) / \ repaint / \ 767 [X] <S> ==========> [P] [D] ======> <P> [Sd] 768 / \ / \ / \ 769 [Sc] [Sd] [X] [Sc] [X] [Sc] 770 771 rm2: Current node X's parent P is red, the sibling S, nephew node Sc and Sd 772 is black. 773 Repaint S into red and P into black. 774 775 <P> [P] 776 / \ / \ 777 [X] [S] ====> [X] <S> 778 / \ / \ 779 [Sc] [Sd] [Sc] [Sd] 780 781 rm3: All of current node X's parent P, the sibling S, nephew node Sc and Sd 782 are black. 783 Unable to satisfy p3 and p4. We have to paint the S into red to satisfy 784 p4 locally. Then recursive to handle P. 785 786 [P] [P] 787 / \ / \ 788 [X] [S] ====> [X] <S> 789 / \ / \ 790 [Sc] [Sd] [Sc] [Sd] 791 792 rm4: Current node X's sibling S is black, nephew node Sc is red and Sd 793 is black. Ignore X's parent P's color (red or black is okay) 794 Unable to satisfy p3 and p4. 795 (1) If X is left node of P, right rotate P. 796 (2) If X is right node of P, left rotate P. 797 (3) Repaint S into red, Sc into black 798 Enter into rm5 to fix. 799 800 {P} {P} 801 {P} / \ / \ 802 / \ r-rotate(S) [X] <Sc> repaint [X] [Sc] 803 [X] [S] ==========> \ ======> \ 804 / \ [S] <S> 805 <Sc> [Sd] \ \ 806 [Sd] [Sd] 807 808 rm5: Current node X's sibling S is black, nephew node Sc is black and Sd 809 is red. Ignore X's parent P's color (red or black is okay) 810 Unable to satisfy p4 (black-violation) 811 (1) If X is left node of P, left rotate P. 812 (2) If X is right node of P, right rotate P. 813 (3) Swap P and S's color (red-violation) 814 (4) Repaint Sd into black. 815 816 {P} [S] {S} 817 / \ l-rotate(P) / \ repaint / \ 818 [X] [S] ==========> {P} <Sd> ======> [P] [Sd] 819 / \ / \ / \ 820 [Sc] <Sd> [X] [Sc] [X] [Sc] 821 */ 822 func (node *xConcSklNode[K, V]) rbRemoveRebalance(x *xNode[V]) { 823 for { 824 if x.isRoot() { 825 return 826 } 827 828 sibling := x.sibling() 829 dir := x.direction() 830 if /* rm1 */ sibling.isRed() { 831 switch dir { 832 case left: 833 node.rbLeftRotate(x.parent) 834 case right: 835 node.rbRightRotate(x.parent) 836 default: 837 // impossible run to here 838 panic( /* debug assertion */ "[x-conc-skl] rbtree remove violate (rm1)") 839 } 840 sibling.color = black 841 x.parent.color = red // ready to enter rm2 842 sibling = x.sibling() 843 } 844 845 var sc, sd *xNode[V] 846 switch /* rm2 */ dir { 847 case left: 848 sc, sd = sibling.left, sibling.right 849 case right: 850 sc, sd = sibling.right, sibling.left 851 default: 852 // impossible run to here 853 panic( /* debug assertion */ "[x-conc-skl] rbtree remove violate (rm2)") 854 } 855 856 if sc.isBlack() && sd.isBlack() { 857 if /* rm2 */ x.parent.isRed() { 858 sibling.color = red 859 x.parent.color = black 860 break 861 } else /* rm3 */ { 862 sibling.color = red 863 x = x.parent 864 continue 865 } 866 } else { 867 if /* rm 4 */ !sc.isNilLeaf() && sc.isRed() { 868 switch dir { 869 case left: 870 node.rbRightRotate(sibling) 871 case right: 872 node.rbLeftRotate(sibling) 873 default: 874 // impossible run to here 875 panic( /* debug assertion */ "[x-conc-skl] rbtree remove violate (rm4)") 876 } 877 sc.color = black 878 sibling.color = red 879 sibling = x.sibling() 880 switch dir { 881 case left: 882 sd = sibling.right 883 case right: 884 sd = sibling.left 885 default: 886 // impossible run to here 887 panic( /* debug assertion */ "[x-conc-skl] rbtree remove violate (rm4)") 888 } 889 } 890 891 switch /* rm5 */ dir { 892 case left: 893 node.rbLeftRotate(x.parent) 894 case right: 895 node.rbRightRotate(x.parent) 896 default: 897 // impossible run to here 898 panic( /* debug assertion */ "[x-conc-skl] rbtree remove violate (rm5)") 899 } 900 sibling.color = x.parent.color 901 x.parent.color = black 902 if !sd.isNilLeaf() { 903 sd.color = black 904 } 905 break 906 } 907 } 908 } 909 910 func (node *xConcSklNode[K, V]) rbSearch(x *xNode[V], fn func(*xNode[V]) int64) *xNode[V] { 911 if x == nil { 912 return nil 913 } 914 915 for aux := x; aux != nil; { 916 res := fn(aux) 917 if res == 0 { 918 return aux 919 } else if res > 0 { 920 aux = aux.right 921 } else { 922 aux = aux.left 923 } 924 } 925 return nil 926 } 927 928 // Inorder traversal to implement the DFS. 929 func (node *xConcSklNode[K, V]) rbDFS(action func(idx int64, color color, val V) bool) { 930 size := atomic.LoadInt64(&node.count) 931 aux := node.root 932 if size < 0 || aux == nil { 933 return 934 } 935 936 stack := make([]*xNode[V], 0, size>>1) 937 defer func() { 938 clear(stack) 939 }() 940 941 for ; !aux.isNilLeaf(); aux = aux.left { 942 stack = append(stack, aux) 943 } 944 945 idx := int64(0) 946 for size = int64(len(stack)); size > 0; size = int64(len(stack)) { 947 if aux = stack[size-1]; !action(idx, aux.color, *aux.vptr) { 948 return 949 } 950 idx++ 951 stack = stack[:size-1] 952 if aux.right != nil { 953 for aux = aux.right; aux != nil; aux = aux.left { 954 stack = append(stack, aux) 955 } 956 } 957 } 958 } 959 960 func (node *xConcSklNode[K, V]) rbRelease() { 961 size := atomic.LoadInt64(&node.count) 962 aux := node.root 963 node.root = nil 964 if size < 0 || aux == nil { 965 return 966 } 967 968 stack := make([]*xNode[V], 0, size>>1) 969 defer func() { 970 clear(stack) 971 }() 972 973 for ; !aux.isNilLeaf(); aux = aux.left { 974 stack = append(stack, aux) 975 } 976 977 for size = int64(len(stack)); size > 0; size = int64(len(stack)) { 978 aux = stack[size-1] 979 r := aux.right 980 aux.right, aux.parent = nil, nil 981 atomic.AddInt64(&node.count, -1) 982 stack = stack[:size-1] 983 if r != nil { 984 for aux = r; aux != nil; aux = aux.left { 985 stack = append(stack, aux) 986 } 987 } 988 } 989 } 990 991 // rbtree rule validation utilities. 992 993 // References: 994 // https://github1s.com/minghu6/rust-minghu6/blob/master/coll_st/src/bst/rb.rs 995 996 // Inorder traversal to validate the rbtree properties. 997 func (node *xConcSklNode[K, V]) rbRedViolationValidate() error { 998 size := atomic.LoadInt64(&node.count) 999 aux := node.root 1000 if size < 0 || aux == nil { 1001 return nil 1002 } 1003 1004 stack := make([]*xNode[V], 0, size>>1) 1005 defer func() { 1006 clear(stack) 1007 }() 1008 1009 for ; !aux.isNilLeaf(); aux = aux.left { 1010 stack = append(stack, aux) 1011 } 1012 1013 for size = int64(len(stack)); size > 0; size = int64(len(stack)) { 1014 if aux = stack[size-1]; aux.isRed() { 1015 if (!aux.parent.isRoot() && aux.parent.isRed()) || 1016 (aux.left.isRed() || aux.right.isRed()) { 1017 return infra.WrapErrorStack(errXSklRbtreeRedViolation) 1018 } 1019 } 1020 1021 stack = stack[:size-1] 1022 if aux.right != nil { 1023 for aux = aux.right; aux != nil; aux = aux.left { 1024 stack = append(stack, aux) 1025 } 1026 } 1027 } 1028 return nil 1029 } 1030 1031 // BFS traversal to load all leaves. 1032 func (node *xConcSklNode[K, V]) rbBFSLeaves() []*xNode[V] { 1033 size := atomic.LoadInt64(&node.count) 1034 aux := node.root 1035 if size < 0 || aux.isNilLeaf() { 1036 return nil 1037 } 1038 1039 leaves := make([]*xNode[V], 0, size>>1+1) 1040 stack := make([]*xNode[V], 0, size>>1) 1041 defer func() { 1042 clear(stack) 1043 }() 1044 stack = append(stack, aux) 1045 1046 for len(stack) > 0 { 1047 aux = stack[0] 1048 l, r := aux.left, aux.right 1049 if /* nil leaves, keep one */ l.isNilLeaf() || r.isNilLeaf() { 1050 leaves = append(leaves, aux) 1051 } 1052 if !l.isNilLeaf() { 1053 stack = append(stack, l) 1054 } 1055 if !r.isNilLeaf() { 1056 stack = append(stack, r) 1057 } 1058 stack = stack[1:] 1059 } 1060 return leaves 1061 } 1062 1063 /* 1064 <X> is a RED node. 1065 [X] is a BLACK node (or NIL). 1066 1067 [13] 1068 / \ 1069 <8> [15] 1070 / \ / \ 1071 [6] [11] [14] [17] 1072 / / 1073 <1> [16] 1074 1075 2-3-4 tree like: 1076 1077 <8> --- [13] --- <15> 1078 / \ / \ 1079 / \ / \ 1080 <1>-[6][11] [14] <16>-[17] 1081 1082 Each leaf node to root node black depth are equal. 1083 */ 1084 func (node *xConcSklNode[K, V]) rbBlackViolationValidate() error { 1085 leaves := node.rbBFSLeaves() 1086 if leaves == nil { 1087 return nil 1088 } 1089 1090 blackDepth := leaves[0].blackDepthTo(node.root) 1091 for i := 1; i < len(leaves); i++ { 1092 if leaves[i].blackDepthTo(node.root) != blackDepth { 1093 return infra.WrapErrorStack(errXSklRbtreeBlackViolation) 1094 } 1095 } 1096 return nil 1097 } 1098 1099 func newXConcSklNode[K infra.OrderedKey, V any]( 1100 key K, 1101 val V, 1102 lvl int32, 1103 mode xNodeMode, 1104 vcmp SklValComparator[V], 1105 ) *xConcSklNode[K, V] { 1106 switch mode { 1107 case unique: 1108 return genXConcSklUniqueNode[K, V](key, val, lvl) 1109 case linkedList: 1110 return genXConcSklLinkedListNode[K, V](key, val, lvl) 1111 case rbtree: 1112 return genXConcSklRbtreeNode[K, V](key, val, vcmp, lvl) 1113 default: 1114 panic("[x-conc-skl] unknown x-node type") 1115 } 1116 } 1117 1118 func newXConcSklHead[K infra.OrderedKey, V any]() *xConcSklNode[K, V] { 1119 head := &xConcSklNode[K, V]{ 1120 key: *new(K), 1121 level: sklMaxLevel, 1122 } 1123 head.flags = set(head.flags, nodeIsHeadFlagBit|nodeInsertedFlagBit) 1124 head.flags = setBitsAs(head.flags, xNodeModeFlagBits, uint32(unique)) 1125 head.indices = make([]*xConcSklNode[K, V], sklMaxLevel) 1126 return head 1127 } 1128 1129 func unlockNodes[K infra.OrderedKey, V any](version uint64, num int32, nodes ...*xConcSklNode[K, V]) { 1130 var prev *xConcSklNode[K, V] 1131 for i := num; i >= 0; i-- { 1132 if nodes[i] != prev { 1133 nodes[i].unlock(version) 1134 prev = nodes[i] 1135 } 1136 } 1137 }