xo-ordinaltree: rbtree ops satisfy gc write barriers
This commit is contained in:
parent
7cab92e128
commit
12f40c8049
4 changed files with 77 additions and 88 deletions
|
|
@ -121,7 +121,7 @@ namespace xo {
|
|||
virtual TaggedPtr self_tp() const;
|
||||
|
||||
/** print on stream @p os **/
|
||||
virtual void display(std::ostream & os) const = 0;
|
||||
virtual void display(std::ostream & os) const;
|
||||
|
||||
// Inherited from IObject..
|
||||
|
||||
|
|
|
|||
|
|
@ -466,10 +466,11 @@ namespace xo {
|
|||
RbNode * adj_root = this->root_;
|
||||
|
||||
std::pair<bool, RbNode *> insert_result
|
||||
= RbUtil::insert_aux(kv_pair,
|
||||
true /*allow_replace_flag*/,
|
||||
this->reduce_fn_,
|
||||
&adj_root);
|
||||
= RbUtil::template insert_aux<node_allocator_type>(this->node_alloc_,
|
||||
kv_pair,
|
||||
true /*allow_replace_flag*/,
|
||||
this->reduce_fn_,
|
||||
&adj_root);
|
||||
|
||||
if (insert_result.first) {
|
||||
++(this->size_);
|
||||
|
|
@ -623,10 +624,10 @@ namespace xo {
|
|||
virtual TaggedPtr self_tp() const {
|
||||
return Reflect::make_tp(const_cast<RedBlackTree *>(this));
|
||||
}
|
||||
#endif
|
||||
virtual void display(std::ostream & os) const final override {
|
||||
os << "<RedBlackTree>";
|
||||
}
|
||||
#endif
|
||||
virtual std::size_t _shallow_size() const final override { return sizeof(*this); }
|
||||
virtual IObject * _shallow_copy(gc::IAlloc * gc) const final override {
|
||||
if constexpr (GcObjectInterface::_requires_gc_hooks) {
|
||||
|
|
|
|||
|
|
@ -82,14 +82,6 @@ namespace xo {
|
|||
}
|
||||
} /*make_leaf*/
|
||||
|
||||
#ifdef OBSOLETE
|
||||
static Node * make_leaf(value_type && kv_pair,
|
||||
ReducedValue const & leaf_rv) {
|
||||
return new Node(kv_pair,
|
||||
std::pair<ReducedValue, ReducedValue>(leaf_rv, leaf_rv));
|
||||
} /*make_leaf*/
|
||||
#endif
|
||||
|
||||
/* return #of key/vaue pairs in tree rooted at x. */
|
||||
static size_t tree_size(Node *x) {
|
||||
if (x)
|
||||
|
|
@ -146,7 +138,7 @@ namespace xo {
|
|||
/* replace root pointer *pp_root with x;
|
||||
* set x parent pointer to nil
|
||||
*/
|
||||
static void replace_root_reparent(Node *x, Node **pp_root) {
|
||||
static void replace_root_reparent(Node * x, Node ** pp_root) {
|
||||
*pp_root = x;
|
||||
if (x)
|
||||
x->parent_ = nullptr;
|
||||
|
|
@ -155,7 +147,11 @@ namespace xo {
|
|||
/** swap values of all members except @ref contents_
|
||||
* between @p *lhs and @p *rhs
|
||||
**/
|
||||
static void swap_locations(Node * lhs, Node * rhs, bool debug_flag) {
|
||||
template <typename NodeAllocator>
|
||||
static void swap_locations(NodeAllocator & alloc,
|
||||
Node * lhs,
|
||||
Node * rhs,
|
||||
bool debug_flag) {
|
||||
scope log(XO_DEBUG(debug_flag));
|
||||
|
||||
assert(lhs->parent() != rhs->parent());
|
||||
|
|
@ -179,7 +175,7 @@ namespace xo {
|
|||
assert(lhs != rhs->right_child() && "expected left-to-right key order");
|
||||
|
||||
if (lhs_parent)
|
||||
lhs_parent->replace_child_reparent(lhs, rhs);
|
||||
lhs_parent->replace_child_reparent(alloc, lhs, rhs);
|
||||
|
||||
/* now have:
|
||||
* - rhs->parent() = lhs_parent
|
||||
|
|
@ -187,7 +183,7 @@ namespace xo {
|
|||
*/
|
||||
|
||||
if (rhs_parent)
|
||||
rhs_parent->replace_child_reparent(rhs, lhs);
|
||||
rhs_parent->replace_child_reparent(alloc, rhs, lhs);
|
||||
|
||||
/* now have:
|
||||
* - lhs->parent() = rhs_parent
|
||||
|
|
@ -211,10 +207,10 @@ namespace xo {
|
|||
Node * rhs_left = rhs->left_child();
|
||||
Node * rhs_right = rhs->right_child();
|
||||
|
||||
lhs->assign_child_reparent(D_Left, rhs_left);
|
||||
lhs->assign_child_reparent(D_Right, rhs_right);
|
||||
rhs->assign_child_reparent(D_Left, lhs_left);
|
||||
rhs->assign_child_reparent(D_Right, lhs_right);
|
||||
lhs->assign_child_reparent(alloc, D_Left, rhs_left);
|
||||
lhs->assign_child_reparent(alloc, D_Right, rhs_right);
|
||||
rhs->assign_child_reparent(alloc, D_Left, lhs_left);
|
||||
rhs->assign_child_reparent(alloc, D_Right, lhs_right);
|
||||
|
||||
//std::swap(lhs->child_v_, rhs->child_v_);
|
||||
|
||||
|
|
@ -318,10 +314,10 @@ namespace xo {
|
|||
virtual TaggedPtr self_tp() const {
|
||||
return Reflect::make_tp(const_cast<Node *>(this));
|
||||
}
|
||||
#endif
|
||||
virtual void display(std::ostream & os) const final override {
|
||||
os << "<Node>";
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual std::size_t _shallow_size() const final override { return sizeof(*this); }
|
||||
/* note: only relevant when GcObjectInterface is xo::IObject */
|
||||
|
|
@ -372,27 +368,10 @@ namespace xo {
|
|||
void assign_color(Color x) { this->color_ = x; }
|
||||
void assign_size(size_t z) { this->size_ = z; }
|
||||
|
||||
void assign_child_reparent(Direction d, Node *new_x) {
|
||||
Node * old_x = this->child_v_[d];
|
||||
|
||||
// trying to fix old_x can be counterproductive,
|
||||
// since old_x->parent_ may already have been corrected,
|
||||
//
|
||||
if (old_x && (old_x->parent_ == this)) {
|
||||
old_x->parent_ = nullptr;
|
||||
}
|
||||
|
||||
this->child_v_[d] = new_x;
|
||||
|
||||
if (new_x) {
|
||||
new_x->parent_ = this;
|
||||
}
|
||||
} /*assign_child_reparent*/
|
||||
|
||||
template <typename NodeAllocator>
|
||||
void assign_child_reparent_2(NodeAllocator & alloc,
|
||||
Direction d,
|
||||
Node * new_x)
|
||||
void assign_child_reparent(NodeAllocator & alloc,
|
||||
Direction d,
|
||||
Node * new_x)
|
||||
{
|
||||
Node * old_x = this->child_v_[d];
|
||||
|
||||
|
|
@ -429,11 +408,14 @@ namespace xo {
|
|||
* - x is nullptr or x.parent is nullptr
|
||||
* - x_new is nullptr or x_new.parent is this
|
||||
*/
|
||||
Direction replace_child_reparent(Node *x, Node *x_new) {
|
||||
template <typename NodeAllocator>
|
||||
Direction replace_child_reparent(NodeAllocator & alloc,
|
||||
Node * x,
|
||||
Node * x_new) {
|
||||
Direction d = this->child_direction(x);
|
||||
|
||||
if (d == D_Left || d == D_Right) {
|
||||
this->assign_child_reparent(d, x_new);
|
||||
if ((d == D_Left) || (d == D_Right)) {
|
||||
this->assign_child_reparent(alloc, d, x_new);
|
||||
return d;
|
||||
} else {
|
||||
return D_Invalid;
|
||||
|
|
|
|||
|
|
@ -355,8 +355,10 @@ namespace xo {
|
|||
* (so any key k' in x satisfies k' > h->key)
|
||||
*
|
||||
*/
|
||||
static RbNode *find_glb_aux(RbNode *x, RbNode *h, Key const &k,
|
||||
bool is_closed) {
|
||||
static RbNode * find_glb_aux(RbNode * x,
|
||||
RbNode * h,
|
||||
Key const & k,
|
||||
bool is_closed) {
|
||||
for (;;) {
|
||||
if (!x)
|
||||
return h;
|
||||
|
|
@ -458,24 +460,25 @@ namespace xo {
|
|||
* / \ / \
|
||||
* T S S R
|
||||
*/
|
||||
static RbNode *rotate(Direction d, RbNode *A,
|
||||
Reduce const & reduce_fn,
|
||||
RbNode **pp_root) {
|
||||
template <typename NodeAllocator>
|
||||
static RbNode * rotate(NodeAllocator & alloc,
|
||||
Direction d,
|
||||
RbNode * A,
|
||||
Reduce const & reduce_fn,
|
||||
bool debug_flag,
|
||||
RbNode ** pp_root) {
|
||||
using xo::scope;
|
||||
using xo::xtag;
|
||||
|
||||
//constexpr char const *c_self = "RbTreeUtil::rotate";
|
||||
constexpr bool c_logging_enabled = false;
|
||||
|
||||
scope log(XO_DEBUG(c_logging_enabled));
|
||||
scope log(XO_DEBUG(debug_flag));
|
||||
|
||||
Direction other_d = other(d);
|
||||
|
||||
RbNode *G = A->parent();
|
||||
RbNode *B = A->child(other_d);
|
||||
//RbNode *R = A->child(d); // not using
|
||||
RbNode *S = B->child(d);
|
||||
//RbNode *T = B->child(other_d); // not using
|
||||
RbNode * G = A->parent();
|
||||
RbNode * B = A->child(other_d);
|
||||
//RbNode * R = A->child(d); // not using
|
||||
RbNode * S = B->child(d);
|
||||
//RbNode * T = B->child(other_d); // not using
|
||||
|
||||
if (log.enabled()) {
|
||||
log("rotate-", (d == D_Left) ? "left" : "right",
|
||||
|
|
@ -493,14 +496,14 @@ namespace xo {
|
|||
}
|
||||
|
||||
/* note: this will set A's old child B to have null parent ptr */
|
||||
A->assign_child_reparent(other_d, S);
|
||||
A->assign_child_reparent(alloc, other_d, S);
|
||||
A->local_recalc_size(reduce_fn);
|
||||
|
||||
B->assign_child_reparent(d, A);
|
||||
B->assign_child_reparent(alloc, d, A);
|
||||
B->local_recalc_size(reduce_fn);
|
||||
|
||||
if (G) {
|
||||
G->replace_child_reparent(A, B);
|
||||
G->replace_child_reparent(alloc, A, B);
|
||||
assert(B->parent() == G);
|
||||
|
||||
/* note: G.size not affected by rotation */
|
||||
|
|
@ -550,18 +553,20 @@ namespace xo {
|
|||
* Promise:
|
||||
* - tree is in RB-shape
|
||||
*/
|
||||
static void fixup_red_shape(Direction d, RbNode *G,
|
||||
template <typename NodeAllocator>
|
||||
static void fixup_red_shape(NodeAllocator & alloc,
|
||||
Direction d,
|
||||
RbNode * G,
|
||||
Reduce const & reduce_fn,
|
||||
RbNode **pp_root) {
|
||||
bool debug_flag,
|
||||
RbNode ** pp_root) {
|
||||
using xo::scope;
|
||||
using xo::xtag;
|
||||
using xo::print::ccs;
|
||||
|
||||
//constexpr char const *c_self = "RbTreeUtil::fixup_red_shape";
|
||||
constexpr bool c_logging_enabled = false;
|
||||
constexpr bool c_excessive_verify_enabled = false;
|
||||
|
||||
scope log(XO_DEBUG(c_logging_enabled));
|
||||
scope log(XO_DEBUG(debug_flag));
|
||||
|
||||
RbNode *P = G->child(d);
|
||||
|
||||
|
|
@ -712,7 +717,7 @@ namespace xo {
|
|||
* / \
|
||||
* R
|
||||
*/
|
||||
RbTreeUtil::rotate(d, P, reduce_fn, pp_root);
|
||||
RbTreeUtil::rotate(alloc, d, P, reduce_fn, debug_flag, pp_root);
|
||||
|
||||
if (c_excessive_verify_enabled)
|
||||
RbTreeUtil::verify_subtree_ok(reduce_fn, S, nullptr /*&black_height*/);
|
||||
|
|
@ -739,7 +744,7 @@ namespace xo {
|
|||
(other_d == D_Left) ? "left" : "right", " at G",
|
||||
xtag("G", G), xtag("G.key", G->key()));
|
||||
|
||||
RbTreeUtil::rotate(other_d, G, reduce_fn, pp_root);
|
||||
RbTreeUtil::rotate(alloc, other_d, G, reduce_fn, debug_flag, pp_root);
|
||||
|
||||
if (c_excessive_verify_enabled) {
|
||||
RbNode *GG = G ? G->parent() : G;
|
||||
|
|
@ -759,7 +764,7 @@ namespace xo {
|
|||
|
||||
return;
|
||||
} /*walk toward root until red violation fixed*/
|
||||
} /*fixup_red_shape*/
|
||||
} /*fixup_red_shape*/
|
||||
|
||||
/* insert key-value pair (key, value) into *pp_root.
|
||||
* on exit *pp_root contains new tree with (key, value) inserted.
|
||||
|
|
@ -837,16 +842,16 @@ namespace xo {
|
|||
kv_pair,
|
||||
reduce_fn.leaf(kv_pair.second));
|
||||
|
||||
N->assign_child_reparent_2(alloc,
|
||||
d,
|
||||
new_node);
|
||||
N->assign_child_reparent(alloc,
|
||||
d,
|
||||
new_node);
|
||||
|
||||
assert(is_red(N->child(d)));
|
||||
|
||||
/* recalculate Node sizes on path [root .. N] */
|
||||
RbTreeUtil::fixup_ancestor_size(reduce_fn, N, debug_flag);
|
||||
/* after adding a node, must rebalance to restore RB-shape */
|
||||
RbTreeUtil::fixup_red_shape(d, N, reduce_fn, pp_root);
|
||||
RbTreeUtil::fixup_red_shape(alloc, d, N, reduce_fn, debug_flag, pp_root);
|
||||
|
||||
//log && log(xtag("path", (char const *)"B"));
|
||||
|
||||
|
|
@ -918,7 +923,7 @@ namespace xo {
|
|||
/* d: direction in P to immediate child N;
|
||||
* also sets N.parent to nil
|
||||
*/
|
||||
Direction d = P->replace_child_reparent(N, nullptr);
|
||||
Direction d = P->replace_child_reparent(alloc, N, nullptr);
|
||||
|
||||
traits::deallocate(alloc, N, 1);
|
||||
|
||||
|
|
@ -1100,7 +1105,7 @@ namespace xo {
|
|||
assert(is_black(P));
|
||||
assert(is_black(N));
|
||||
|
||||
RbTreeUtil::rotate(d, P, reduce_fn, pp_root);
|
||||
RbTreeUtil::rotate(alloc, d, P, reduce_fn, debug_flag, pp_root);
|
||||
|
||||
/* after rotation d at P:
|
||||
*
|
||||
|
|
@ -1217,7 +1222,8 @@ namespace xo {
|
|||
* - D at h
|
||||
*/
|
||||
|
||||
RbTreeUtil::rotate(other_d, S, reduce_fn, pp_root);
|
||||
RbTreeUtil::rotate(alloc,
|
||||
other_d, S, reduce_fn, debug_flag, pp_root);
|
||||
|
||||
assert(P->child(other_d) == C);
|
||||
|
||||
|
|
@ -1292,7 +1298,7 @@ namespace xo {
|
|||
* - S (+also C,D) at h
|
||||
*/
|
||||
|
||||
RbTreeUtil::rotate(d, P, reduce_fn, pp_root);
|
||||
RbTreeUtil::rotate(alloc, d, P, reduce_fn, debug_flag, pp_root);
|
||||
|
||||
/* after rotate at P toward d: *
|
||||
*
|
||||
|
|
@ -1438,7 +1444,7 @@ namespace xo {
|
|||
* W
|
||||
*/
|
||||
if (P)
|
||||
P->replace_child_reparent(N, R);
|
||||
P->replace_child_reparent(alloc, N, R);
|
||||
|
||||
/*
|
||||
* here the triangle ascii art indicates a tree structure,
|
||||
|
|
@ -1452,8 +1458,8 @@ namespace xo {
|
|||
* / . R Y
|
||||
* W
|
||||
*/
|
||||
R->assign_child_reparent(D_Left, N);
|
||||
R->assign_child_reparent(D_Right, Y);
|
||||
R->assign_child_reparent(alloc, D_Left, N);
|
||||
R->assign_child_reparent(alloc, D_Right, Y);
|
||||
/*
|
||||
* here the triangle ascii art indicates a tree structure,
|
||||
* of arbitrary size
|
||||
|
|
@ -1468,8 +1474,8 @@ namespace xo {
|
|||
* / \
|
||||
* R Y
|
||||
*/
|
||||
N->assign_child_reparent(D_Left, W);
|
||||
N->assign_child_reparent(D_Right, nullptr);
|
||||
N->assign_child_reparent(alloc, D_Left, W);
|
||||
N->assign_child_reparent(alloc, D_Right, nullptr);
|
||||
/*
|
||||
* here the triangle ascii art indicates a tree structure,
|
||||
* of arbitrary size
|
||||
|
|
@ -1519,7 +1525,7 @@ namespace xo {
|
|||
* everything except RbNode.contents_.
|
||||
* Annoying but necessary to have stable Node memory locations
|
||||
*/
|
||||
RbNode::swap_locations(R, N, debug_flag);
|
||||
RbNode::swap_locations(alloc, R, N, debug_flag);
|
||||
|
||||
/* swapping locations invalidates RbNode.reduced_.
|
||||
* But correctness will be restored in erase_1child_aux()
|
||||
|
|
@ -1592,7 +1598,7 @@ namespace xo {
|
|||
/* replace pointer to N with nil in N's parent. */
|
||||
|
||||
if (P) {
|
||||
P->replace_child_reparent(N, nullptr);
|
||||
P->replace_child_reparent(alloc, N, nullptr);
|
||||
|
||||
log && log("fixup_ancestor_size starting at P");
|
||||
RbTreeUtil::fixup_ancestor_size(reduce_fn, P, debug_flag);
|
||||
|
|
@ -1613,7 +1619,7 @@ namespace xo {
|
|||
*/
|
||||
}
|
||||
} else /*N->is_black()*/ {
|
||||
RbNode *R = N->left_child();
|
||||
RbNode * R = N->left_child();
|
||||
|
||||
if (!R)
|
||||
R = N->right_child();
|
||||
|
|
@ -1628,7 +1634,7 @@ namespace xo {
|
|||
R->assign_color(C_Black);
|
||||
|
||||
if (P) {
|
||||
P->replace_child_reparent(N, R);
|
||||
P->replace_child_reparent(alloc, N, R);
|
||||
log && log("fixup_ancestor_size starting at P");
|
||||
RbTreeUtil::fixup_ancestor_size(reduce_fn, P, debug_flag);
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue