g_tree_node_next_version (GTree *tree,
GTreeNode *node)
{
+ if (!node)
+ return NULL;
+
g_assert(node->version(NOW) <= tree->version);
if (node->version(NOW) == tree->version)
while (node->parent(NOW) &&
g_tree_priority (node) < g_tree_priority (node->parent(NOW)))
{
- GTreeNode *const sp = node->parent(NOW)->parent(NOW);
- GTreeNode *const p = node->parent(NOW);
+ GTreeNode *sp, *p;
+
+ /* we'll be changing both of these nodes */
+ p = g_tree_node_next_version (tree, node->parent(NOW));
+ sp = g_tree_node_next_version (tree, p->parent(NOW));
+
if (p->left(NOW) == node)
- g_tree_node_rotate_right (tree, p);
+ node = g_tree_node_rotate_right (tree, p);
else
- g_tree_node_rotate_left (tree, p);
+ node = g_tree_node_rotate_left (tree, p);
if (!sp)
{
tree->roots[0].root = node;
}
else if (sp->left(NOW) == p)
- sp->left(NOW) = node;
+ sp->v[0].left = node;
else
- sp->right(NOW) = node;
+ sp->v[0].right = node;
}
}
/* rotate the node down the tree, maintaining the heap property */
while (node->left_child(NOW) || node->right_child(NOW))
{
+ /* we're changing this node, make sure our pointer will stay valid
+ when we rotate it */
+ node = g_tree_node_next_version (tree, node);
+
if (!node->left_child(NOW) ||
(node->right_child(NOW) &&
g_tree_priority (node->left(NOW)) >
parent->v[0].right = node->right(NOW);
}
}
-
- if (!steal)
+
+ /* only really delete the node if it's in the current version, otherwise
+ it needs to be remembered */
+ if (node->nv == 1 && node->version(NOW) == tree->version)
{
- if (tree->key_destroy_func)
- tree->key_destroy_func (node->data->key);
- if (tree->value_destroy_func)
- tree->value_destroy_func (node->data->value);
- }
+ if (!steal)
+ {
+ if (tree->key_destroy_func)
+ tree->key_destroy_func (node->data->key);
+ if (tree->value_destroy_func)
+ tree->value_destroy_func (node->data->value);
+ }
- g_slice_free (GTreeNode, node);
+ g_slice_free (GTreeNodeData, node->data);
+ g_slice_free1 (sizeof(GTreeNodeVersion) *
+ (node->version(NOW) == 0 ? 1 : MAX_IN_DEGREE + 1),
+ node->v);
+ g_slice_free (GTreeNode, node);
+ }
tree->nnodes--;
{
GTreeNode *right;
- right = node->right(NOW);
+ g_assert (node->version(NOW) == tree->version);
- node = g_tree_node_next_version (tree, node);
- right = g_tree_node_next_version (tree, right);
+ right = g_tree_node_next_version (tree, node->right(NOW));
if (right->left_child(NOW))
{
{
GTreeNode *left;
- left = node->left(NOW);
+ g_assert (node->version(NOW) == tree->version);
- node = g_tree_node_next_version (tree, node);
- left = g_tree_node_next_version (tree, left);
+ left = g_tree_node_next_version (tree, node->left(NOW));
if (left->right_child(NOW))
{