/* * Replace node x with node y * NOTE: block header of y is not changed */ static ERTS_INLINE void replace(AOFF_RBTree_t **root, AOFF_RBTree_t *x, AOFF_RBTree_t *y) { if (!x->parent) { RBT_ASSERT(*root == x); *root = y; } else if (x == x->parent->left) x->parent->left = y; else { RBT_ASSERT(x == x->parent->right); x->parent->right = y; } if (x->left) { RBT_ASSERT(x->left->parent == x); x->left->parent = y; } if (x->right) { RBT_ASSERT(x->right->parent == x); x->right->parent = y; } y->flags = x->flags; y->parent = x->parent; y->right = x->right; y->left = x->left; y->max_sz = x->max_sz; lower_max_size(y, NULL); DESTROY_TREE_NODE(x); }
static void aoff_unlink_free_block(Allctr_t *allctr, Block_t *blk) { AOFFAllctr_t* alc = (AOFFAllctr_t*)allctr; AOFF_RBTree_t* del = (AOFF_RBTree_t*)blk; AOFF_Carrier_t *crr = (AOFF_Carrier_t*) FBLK_TO_MBC(&del->hdr); ASSERT(crr->rbt_node.hdr.bhdr == crr->root->max_sz); HARD_CHECK_TREE(&crr->crr, alc->blk_order, crr->root, 0); if (alc->blk_order == FF_BF) { ASSERT(del->flags & IS_BF_FLG); if (IS_LIST_ELEM(del)) { /* Remove from list */ ASSERT(LIST_PREV(del)); ASSERT(LIST_PREV(del)->flags & IS_BF_FLG); LIST_NEXT(LIST_PREV(del)) = LIST_NEXT(del); if (LIST_NEXT(del)) { ASSERT(LIST_NEXT(del)->flags & IS_BF_FLG); LIST_PREV(LIST_NEXT(del)) = LIST_PREV(del); } return; } else if (LIST_NEXT(del)) { /* Replace tree node by next element in list... */ ASSERT(AOFF_BLK_SZ(LIST_NEXT(del)) == AOFF_BLK_SZ(del)); ASSERT(IS_LIST_ELEM(LIST_NEXT(del))); replace(&crr->root, (AOFF_RBTree_t*)del, LIST_NEXT(del)); HARD_CHECK_TREE(&crr->crr, alc->blk_order, crr->root, 0); return; } } rbt_delete(&crr->root, (AOFF_RBTree_t*)del); HARD_CHECK_TREE(&crr->crr, alc->blk_order, crr->root, 0); /* Update the carrier tree with a potentially new (lower) max_sz */ if (crr->root) { if (crr->rbt_node.hdr.bhdr == crr->root->max_sz) { return; } ASSERT(crr->rbt_node.hdr.bhdr > crr->root->max_sz); crr->rbt_node.hdr.bhdr = crr->root->max_sz; } else { crr->rbt_node.hdr.bhdr = 0; } lower_max_size(&crr->rbt_node, NULL); }
static void rbt_delete(AOFF_RBTree_t** root, AOFF_RBTree_t* del) { Uint spliced_is_black; AOFF_RBTree_t *x, *y, *z = del; AOFF_RBTree_t null_x; /* null_x is used to get the fixup started when we splice out a node without children. */ HARD_CHECK_IS_MEMBER(*root, del); null_x.parent = NULL; /* Remove node from tree... */ /* Find node to splice out */ if (!z->left || !z->right) y = z; else /* Set y to z:s successor */ for(y = z->right; y->left; y = y->left); /* splice out y */ x = y->left ? y->left : y->right; spliced_is_black = IS_BLACK(y); if (x) { x->parent = y->parent; } else if (spliced_is_black) { x = &null_x; x->flags = 0; SET_BLACK(x); x->right = x->left = NULL; x->max_sz = 0; x->parent = y->parent; y->left = x; } if (!y->parent) { RBT_ASSERT(*root == y); *root = x; } else { if (y == y->parent->left) { y->parent->left = x; } else { RBT_ASSERT(y == y->parent->right); y->parent->right = x; } if (y->parent != z) { lower_max_size(y->parent, (y==z ? NULL : z)); } } if (y != z) { /* We spliced out the successor of z; replace z by the successor */ ASSERT(z != &null_x); replace(root, z, y); lower_max_size(y, NULL); } if (spliced_is_black) { /* We removed a black node which makes the resulting tree violate the Red-Black Tree properties. Fixup tree... */ while (IS_BLACK(x) && x->parent) { /* * x has an "extra black" which we move up the tree * until we reach the root or until we can get rid of it. * * y is the sibbling of x */ if (x == x->parent->left) { y = x->parent->right; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); left_rotate(root, x->parent); y = x->parent->right; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->left) && IS_BLACK(y->right)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->right)) { SET_BLACK(y->left); SET_RED(y); right_rotate(root, y); y = x->parent->right; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->right); SET_BLACK(y->right); left_rotate(root, x->parent); x = *root; break; } } else { RBT_ASSERT(x == x->parent->right); y = x->parent->left; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); right_rotate(root, x->parent); y = x->parent->left; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->right) && IS_BLACK(y->left)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->left)) { SET_BLACK(y->right); SET_RED(y); left_rotate(root, y); y = x->parent->left; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->left); SET_BLACK(y->left); right_rotate(root, x->parent); x = *root; break; } } } SET_BLACK(x); if (null_x.parent) { if (null_x.parent->left == &null_x) null_x.parent->left = NULL; else { RBT_ASSERT(null_x.parent->right == &null_x); null_x.parent->right = NULL; } RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } else if (*root == &null_x) { *root = NULL; RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } } }
static void aoff_unlink_free_block(Allctr_t *allctr, Block_t *del, Uint32 flags) { AOFFAllctr_t *alc = (AOFFAllctr_t *) allctr; AOFF_RBTree_t **root = ((flags & ERTS_ALCU_FLG_SBMBC) ? &alc->sbmbc_root : &alc->mbc_root); Uint spliced_is_black; AOFF_RBTree_t *x, *y, *z = (AOFF_RBTree_t *) del; AOFF_RBTree_t null_x; /* null_x is used to get the fixup started when we splice out a node without children. */ null_x.parent = NULL; #ifdef HARD_DEBUG check_tree(*root, 0); #endif /* Remove node from tree... */ /* Find node to splice out */ if (!z->left || !z->right) y = z; else /* Set y to z:s successor */ for(y = z->right; y->left; y = y->left); /* splice out y */ x = y->left ? y->left : y->right; spliced_is_black = IS_BLACK(y); if (x) { x->parent = y->parent; } else if (spliced_is_black) { x = &null_x; x->flags = 0; SET_BLACK(x); x->right = x->left = NULL; x->max_sz = 0; x->parent = y->parent; y->left = x; } if (!y->parent) { RBT_ASSERT(*root == y); *root = x; } else { if (y == y->parent->left) { y->parent->left = x; } else { RBT_ASSERT(y == y->parent->right); y->parent->right = x; } if (y->parent != z) { lower_max_size(y->parent, (y==z ? NULL : z)); } } if (y != z) { /* We spliced out the successor of z; replace z by the successor */ replace(root, z, y); } if (spliced_is_black) { /* We removed a black node which makes the resulting tree violate the Red-Black Tree properties. Fixup tree... */ while (IS_BLACK(x) && x->parent) { /* * x has an "extra black" which we move up the tree * until we reach the root or until we can get rid of it. * * y is the sibbling of x */ if (x == x->parent->left) { y = x->parent->right; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); left_rotate(root, x->parent); y = x->parent->right; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->left) && IS_BLACK(y->right)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->right)) { SET_BLACK(y->left); SET_RED(y); right_rotate(root, y); y = x->parent->right; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->right); SET_BLACK(y->right); left_rotate(root, x->parent); x = *root; break; } } else { RBT_ASSERT(x == x->parent->right); y = x->parent->left; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); right_rotate(root, x->parent); y = x->parent->left; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->right) && IS_BLACK(y->left)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->left)) { SET_BLACK(y->right); SET_RED(y); left_rotate(root, y); y = x->parent->left; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->left); SET_BLACK(y->left); right_rotate(root, x->parent); x = *root; break; } } } SET_BLACK(x); if (null_x.parent) { if (null_x.parent->left == &null_x) null_x.parent->left = NULL; else { RBT_ASSERT(null_x.parent->right == &null_x); null_x.parent->right = NULL; } RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } else if (*root == &null_x) { *root = NULL; RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } } DESTROY_TREE_NODE(del); #ifdef HARD_DEBUG check_tree(*root, 0); #endif }