From 4c5aad588363736069cf75ddb4d6669a9b04e10f Mon Sep 17 00:00:00 2001 From: krangelov Date: Fri, 3 Sep 2021 20:01:13 +0200 Subject: [PATCH] use reference counting to release the namespaces --- src/runtime/c/pgf/namespace.h | 169 +++++++++++++++++++++++++--------- src/runtime/c/pgf/reader.cxx | 4 +- 2 files changed, 131 insertions(+), 42 deletions(-) diff --git a/src/runtime/c/pgf/namespace.h b/src/runtime/c/pgf/namespace.h index 1d1be21fa..686f18bd0 100644 --- a/src/runtime/c/pgf/namespace.h +++ b/src/runtime/c/pgf/namespace.h @@ -10,91 +10,136 @@ template using Namespace = ref>; template -class PGF_INTERNAL_DECL Node { +class PGF_INTERNAL_DECL Node +{ public: + size_t ref_count; + size_t sz; ref value; ref left; ref right; static - ref new_node(ref value) { + ref new_node(ref value) + { ref node = current_db->malloc(); - node->sz = 1; - node->value = value; - node->left = 0; - node->right = 0; + node->ref_count = 1; + node->sz = 1; + node->value = value; + node->left = 0; + node->right = 0; return node; } static - ref new_node(ref value, ref left, ref right) { + ref new_node(ref value, ref left, ref right) + { ref node = current_db->malloc(); - node->sz = 1+namespace_size(left)+namespace_size(right); - node->value = value; - node->left = left; - node->right = right; + node->ref_count = 1; + node->sz = 1+namespace_size(left)+namespace_size(right); + node->value = value; + node->left = left; + node->right = right; return node; } static - ref balanceL(ref value, ref left, ref right) { + ref balanceL(ref value, ref left, ref right) + { if (right == 0) { if (left == 0) { return new_node(value); } else { if (left->left == 0) { if (left->right == 0) { + left->ref_count++; return new_node(value,left,0); } else { + Namespace new_left = new_node(left->value); + Namespace new_right = new_node(value); return new_node(left->right->value, - new_node(left->value), - new_node(value)); + new_left, + new_right); } } else { if (left->right == 0) { + Namespace new_right = new_node(value); + left->left->ref_count++; return new_node(left->value, left->left, - new_node(value)); + new_right); } else { if (left->right->sz < 2 * left->left->sz) { + left->left->ref_count++; + left->right->ref_count++; + Namespace new_right = + new_node(value, + left->right, + 0); return new_node(left->value, left->left, - new_node(value, - left->right, - 0)); + new_right); } else { + left->left->ref_count++; + if (left->right->left != 0) + left->right->left->ref_count++; + if (left->right->right != 0) + left->right->right->ref_count++; + Namespace new_left = + new_node(left->value, + left->left, + left->right->left); + Namespace new_right = + new_node(value, + left->right->right, + 0); return new_node(left->right->value, - new_node(left->value, - left->left, - left->right->left), - new_node(value, - left->right->right, - 0)); + new_left, + new_right); } } } } } else { if (left == 0) { + right->ref_count++; return new_node(value,0,right); } else { if (left->sz > 3*right->sz) { - if (left->right->sz < 2*left->left->sz) + if (left->right->sz < 2*left->left->sz) { + left->left->ref_count++; + left->right->ref_count++; + right->ref_count++; + Namespace new_right = + new_node(value, + left->right, + right); return new_node(left->value, left->left, - new_node(value, - left->right, - right)); - else + new_right); + } else { + left->left->ref_count++; + if (left->right->left != 0) + left->right->left->ref_count++; + if (left->right->right != 0) + left->right->right->ref_count++; + right->ref_count++; + Namespace new_left = + new_node(left->value, + left->left, + left->right->left); + Namespace new_right = + new_node(value, + left->right->right, + right); return new_node(left->right->value, - new_node(left->value, - left->left, - left->right->left), - new_node(value, - left->right->right, - right)); + new_left, + new_right); + } } else { + left->ref_count++; + right->ref_count++; return new_node(value,left,right); } } @@ -102,15 +147,18 @@ public: } static - ref balanceR(ref value, ref left, ref right) { + ref balanceR(ref value, ref left, ref right) + { if (left == 0) { if (right == 0) { return new_node(value); } else { if (right->left == 0) { if (right->right == 0) { + right->ref_count++; return new_node(value,0,right); } else { + right->right->ref_count++; Namespace new_left = new_node(value); return new_node(right->value, @@ -128,6 +176,8 @@ public: new_right); } else { if (right->left->sz < 2 * right->right->sz) { + right->left->ref_count++; + right->right->ref_count++; Namespace new_left = new_node(value, 0, @@ -136,6 +186,11 @@ public: new_left, right->right); } else { + if (right->left->left != 0) + right->left->left->ref_count++; + if (right->left->right != 0) + right->left->right->ref_count++; + right->right->ref_count++; Namespace new_left = new_node(value, 0, @@ -153,10 +208,14 @@ public: } } else { if (right == 0) { + left->ref_count++; return new_node(value,left,0); } else { if (right->sz > 3*left->sz) { if (right->left->sz < 2*right->right->sz) { + left->ref_count++; + right->left->ref_count++; + right->right->ref_count++; Namespace new_left = new_node(value, left, @@ -165,6 +224,12 @@ public: new_left, right->right); } else { + left->ref_count++; + if (right->left->left != 0) + right->left->left->ref_count++; + if (right->left->right != 0) + right->left->right->ref_count++; + right->right->ref_count++; Namespace new_left = new_node(value, left, @@ -175,10 +240,11 @@ public: right->right); return new_node(right->left->value, new_left, - new_right - ); + new_right); } } else { + left->ref_count++; + right->ref_count++; return new_node(value,left,right); } } @@ -207,12 +273,19 @@ Namespace namespace_insert(Namespace map, ref value) int cmp = textcmp(&value->name,&map->value->name); if (cmp < 0) { Namespace left = namespace_insert(map->left, value); - return Node::balanceL(map->value,left,map->right); + Namespace node = Node::balanceL(map->value,left,map->right); + namespace_release(left); + return node; } else if (cmp > 0) { Namespace right = namespace_insert(map->right, value); - return Node::balanceR(map->value, map->left, right); - } else + Namespace node = Node::balanceR(map->value, map->left, right); + namespace_release(right); + return node; + } else { + map->left->ref_count++; + map->right->ref_count++; return Node::new_node(value,map->left,map->right); + } } template @@ -256,4 +329,18 @@ void namespace_iter(Namespace map, PgfItor* itor, PgfExn *err) if (err->type != PGF_EXN_NONE) return; } + +template +void namespace_release(Namespace node) +{ + if (node == 0) + return; + + if (!(--node->ref_count)) { + namespace_release(node->left); + namespace_release(node->right); + DB::free(node); + } +} + #endif diff --git a/src/runtime/c/pgf/reader.cxx b/src/runtime/c/pgf/reader.cxx index beafda619..b9b8b3e2c 100644 --- a/src/runtime/c/pgf/reader.cxx +++ b/src/runtime/c/pgf/reader.cxx @@ -154,7 +154,9 @@ Namespace PgfReader::read_namespace(ref (PgfReader::*read_value)()) Namespace nmsp = 0; for (size_t i = 0; i < len; i++) { ref value = (this->*read_value)(); - nmsp = namespace_insert(nmsp, value); + Namespace new_nmsp = namespace_insert(nmsp, value); + namespace_release(nmsp); + nmsp = new_nmsp; } return nmsp; }