xo-ordinaltree: alloc-aware node reparenting. WIP.

This commit is contained in:
Roland Conybeare 2025-12-04 18:58:58 -05:00
commit 451425af87
3 changed files with 39 additions and 5 deletions

View file

@ -71,6 +71,9 @@ namespace xo {
using allocator_type = Allocator; using allocator_type = Allocator;
using allocator_traits = xo::gc::gc_allocator_traits<Allocator>; using allocator_traits = xo::gc::gc_allocator_traits<Allocator>;
/** WARNING:
* - GcObjectInterface is typed + assoc type is pair<Key const, Value>.
**/
using GcObjectInterface = allocator_traits::object_interface_type; using GcObjectInterface = allocator_traits::object_interface_type;
using ReducedValue = typename Reduce::value_type; using ReducedValue = typename Reduce::value_type;
using RbUtil = detail::RbTreeUtil<Key, Value, Reduce, GcObjectInterface>; using RbUtil = detail::RbTreeUtil<Key, Value, Reduce, GcObjectInterface>;

View file

@ -371,13 +371,14 @@ namespace xo {
void assign_size(size_t z) { this->size_ = z; } void assign_size(size_t z) { this->size_ = z; }
void assign_child_reparent(Direction d, Node *new_x) { void assign_child_reparent(Direction d, Node *new_x) {
Node *old_x = this->child_v_[d]; Node * old_x = this->child_v_[d];
// trying to fix old_x can be counterproductive, // trying to fix old_x can be counterproductive,
// since old_x->parent_ may already have been corrected, // since old_x->parent_ may already have been corrected,
// //
if (old_x && (old_x->parent_ == this)) if (old_x && (old_x->parent_ == this)) {
old_x->parent_ = nullptr; old_x->parent_ = nullptr;
}
this->child_v_[d] = new_x; this->child_v_[d] = new_x;
@ -386,6 +387,35 @@ namespace xo {
} }
} /*assign_child_reparent*/ } /*assign_child_reparent*/
template <typename NodeAllocator>
void assign_child_reparent_2(NodeAllocator & alloc,
Direction d,
Node * new_x)
{
Node * old_x = this->child_v_[d];
using node_allocator_traits = xo::gc::gc_allocator_traits<NodeAllocator>;
using kvpair_allocator_type = node_allocator_traits::template rebind_alloc<value_type>;
kvpair_allocator_type assign_alloc(alloc);
// 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;
}
Node ** child_addr = &(this->child_v_[d]);
this->_gc_assign_member(child_addr, new_x, assign_alloc);
//this->child_v_[d] = new_x;
if (new_x) {
this->_gc_assign_member(&(new_x->parent_), this, assign_alloc);
//new_x->parent_ = this;
}
} /*assign_child_reparent*/
/* replace child that points to x, with child that points to x_new /* replace child that points to x, with child that points to x_new
* and return direction of the child that was replaced * and return direction of the child that was replaced
* *

View file

@ -822,7 +822,7 @@ namespace xo {
d = ((kv_pair.first < N->key()) ? D_Left : D_Right); d = ((kv_pair.first < N->key()) ? D_Left : D_Right);
/* insert into left subtree somewhere */ /* insert into left subtree somewhere */
RbNode *C = N->child(d); RbNode * C = N->child(d);
if (!C) if (!C)
break; break;
@ -835,10 +835,11 @@ namespace xo {
if (N) { if (N) {
RbNode * new_node = RbNode::make_leaf(alloc, RbNode * new_node = RbNode::make_leaf(alloc,
kv_pair, kv_pair,
reduce_fn.leaf(kv_pair.second)); reduce_fn.leaf(kv_pair.second));
N->assign_child_reparent(d, new_node); N->assign_child_reparent_2(alloc,
d,
new_node);
assert(is_red(N->child(d))); assert(is_red(N->child(d)));