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  }