u3: corrects recursive deletion in _ch_node_del(), refactors

This commit is contained in:
Joe Bryan 2024-07-29 11:16:16 -04:00
parent da0aad4ceb
commit 3f7ccb7ee6

View File

@ -270,12 +270,10 @@ u3h_put(u3p(u3h_root) har_p, u3_noun key, u3_noun val)
}
}
static c3_o _ch_slot_del(u3h_slot*, u3_noun, c3_w, c3_w, c3_w*);
/* _ch_buck_del(): delete from bucket
*/
static c3_o
_ch_buck_del(u3h_slot* sot_w, u3_noun key, c3_w *use_w)
_ch_buck_del(u3h_slot* sot_w, u3_noun key)
{
u3h_buck* hab_u = u3h_slot_to_node(*sot_w);
c3_w fin_w = hab_u->len_w;
@ -299,36 +297,40 @@ _ch_buck_del(u3h_slot* sot_w, u3_noun key, c3_w *use_w)
{
hab_u->len_w--;
u3_assert(c3y == u3h_slot_is_noun(hab_u->sot_w[fin_w]));
//u3z(u3h_slot_to_noun(hab_u->sot_w[fin_w]));
// u3_assert(c3y == u3h_slot_is_noun(hab_u->sot_w[fin_w]));
for ( i_w = fin_w; i_w < hab_u->len_w; i_w++ ) {
hab_u->sot_w[i_w] = hab_u->sot_w[i_w + 1];
}
*use_w -= 1;
return c3y;
}
}
static c3_o _ch_some_del(u3h_slot*, u3_noun, c3_w, c3_w, c3_w*);
static c3_o _ch_some_del(u3h_slot*, u3_noun, c3_w, c3_w);
/* _ch_slot_del(): delete from slot
*/
static c3_o
_ch_slot_del(u3h_slot* sot_w, u3_noun key, c3_w lef_w, c3_w rem_w, c3_w* use_w) {
_ch_slot_del(u3h_slot* sot_w, u3_noun key, c3_w lef_w, c3_w rem_w)
{
if ( c3y == u3h_slot_is_noun(*sot_w) ) {
u3_noun kev = u3h_slot_to_noun(*sot_w);
*sot_w = 0;
u3z(kev);
*use_w -= 1;
return c3y;
} else {
return _ch_some_del(sot_w, key, lef_w, rem_w, use_w);
}
else {
return _ch_some_del(sot_w, key, lef_w, rem_w);
}
}
/* _ch_slot_del(): delete from node
*/
static c3_o
_ch_node_del(u3h_slot* sot_w, u3_noun key, c3_w lef_w, c3_w rem_w, c3_w* use_w)
_ch_node_del(u3h_slot* sot_w, u3_noun key, c3_w lef_w, c3_w rem_w)
{
u3h_node* han_u = (u3h_node*) u3h_slot_to_node(*sot_w);
u3h_slot* tos_w;
c3_w bit_w, inx_w, map_w, i_w;
@ -338,49 +340,61 @@ _ch_node_del(u3h_slot* sot_w, u3_noun key, c3_w lef_w, c3_w rem_w, c3_w* use_w)
map_w = han_u->map_w;
inx_w = _ch_popcount(CUT_END(map_w, bit_w));
tos_w = &(han_u->sot_w[inx_w]);
// nothing at slot, no-op
if ( !BIT_SET(map_w, bit_w) ) {
return c3n;
}
c3_w ken_w;
u3h_slot kes_w;
u3h_slot don_w = han_u->sot_w[inx_w];
c3_w len_w = _ch_popcount(map_w);
if ( len_w == 2 && ((ken_w = (0 == inx_w) ? 1 : 0),
(kes_w = han_u->sot_w[ken_w]),
(c3y == u3h_slot_is_noun(don_w) && c3y == u3h_slot_is_noun(kes_w))) ) {
*sot_w = kes_w;
u3z(u3h_slot_to_noun(don_w));
*use_w -= 1;
u3a_wfree(han_u);
if ( c3n == _ch_slot_del(tos_w, key, lef_w, rem_w) ) {
// nothing deleted
return c3n;
}
else if ( 0 != *tos_w ) {
// something deleted, but slot still has value
return c3y;
}
c3_o ret_o = _ch_slot_del(&han_u->sot_w[inx_w], key, lef_w, rem_w, use_w);
if ( c3y == ret_o && c3y == u3h_slot_is_null(han_u->sot_w[inx_w]) ) {
han_u->map_w &= ~(1 << bit_w);
for ( i_w = inx_w; i_w < len_w; i_w++ ) {
han_u->sot_w[i_w] = han_u->sot_w[i_w + 1];
else {
// shrink!
c3_w i_w, ken_w, len_w = _ch_popcount(map_w);
u3h_slot kes_w;
if ( 2 == len_w && ((ken_w = (0 == inx_w) ? 1 : 0),
(kes_w = han_u->sot_w[ken_w]),
(c3y == u3h_slot_is_noun(kes_w))) )
{
// only one side left, and the other is a noun. debucketize.
*sot_w = kes_w;
u3a_wfree(han_u);
}
else {
// shrink node in place; don't reallocate, we could be low on memory
//
han_u->map_w &= ~(1 << bit_w);
--len_w;
for ( i_w = inx_w; i_w < len_w; i_w++ ) {
han_u->sot_w[i_w] = han_u->sot_w[i_w + 1];
}
}
return c3y;
}
return ret_o;
}
/* _ch_some_del(): delete from node or buck
*/
static c3_o
_ch_some_del(u3h_slot* sot_w, u3_noun key, c3_w lef_w, c3_w rem_w, c3_w* use_w)
_ch_some_del(u3h_slot* sot_w, u3_noun key, c3_w lef_w, c3_w rem_w)
{
if ( 0 == lef_w ) {
return _ch_buck_del(sot_w, key, use_w);
return _ch_buck_del(sot_w, key);
}
//u3h_node* han_u = (u3h_node*)han_v;
//if ( _ch_popcount(han_u))
return _ch_node_del(sot_w, key, lef_w, rem_w, use_w);
return _ch_node_del(sot_w, key, lef_w, rem_w);
}
/** TODO: this has a bug where the freeing a hamt that this has been called with failes
* most likelly memroy mgmt
/* u3h_del(); delete from hashtable.
*/
void
u3h_del(u3p(u3h_root) har_p, u3_noun key)
@ -391,10 +405,10 @@ u3h_del(u3p(u3h_root) har_p, u3_noun key)
c3_w rem_w = CUT_END(mug_w, 25);
u3h_slot* sot_w = &(har_u->sot_w[inx_w]);
if ( c3y == u3h_slot_is_null(*sot_w) ) {
return;
} else {
_ch_slot_del(sot_w, key, 25, rem_w, &(har_u->use_w));
if ( (c3n == u3h_slot_is_null(*sot_w))
&& (c3y == _ch_slot_del(sot_w, key, 25, rem_w)) )
{
har_u->use_w--;
}
}