mirror of
https://github.com/urbit/vere.git
synced 2024-09-11 03:45:31 +03:00
u3: corrects recursive deletion in _ch_node_del(), refactors
This commit is contained in:
parent
da0aad4ceb
commit
3f7ccb7ee6
@ -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--;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user