mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-21 09:02:50 -06:00
use reference counting to release the namespaces
This commit is contained in:
@@ -10,16 +10,21 @@ template <class V>
|
|||||||
using Namespace = ref<Node<V>>;
|
using Namespace = ref<Node<V>>;
|
||||||
|
|
||||||
template <class V>
|
template <class V>
|
||||||
class PGF_INTERNAL_DECL Node {
|
class PGF_INTERNAL_DECL Node
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
size_t ref_count;
|
||||||
|
|
||||||
size_t sz;
|
size_t sz;
|
||||||
ref<V> value;
|
ref<V> value;
|
||||||
ref<Node> left;
|
ref<Node> left;
|
||||||
ref<Node> right;
|
ref<Node> right;
|
||||||
|
|
||||||
static
|
static
|
||||||
ref<Node> new_node(ref<V> value) {
|
ref<Node> new_node(ref<V> value)
|
||||||
|
{
|
||||||
ref<Node> node = current_db->malloc<Node>();
|
ref<Node> node = current_db->malloc<Node>();
|
||||||
|
node->ref_count = 1;
|
||||||
node->sz = 1;
|
node->sz = 1;
|
||||||
node->value = value;
|
node->value = value;
|
||||||
node->left = 0;
|
node->left = 0;
|
||||||
@@ -28,8 +33,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
ref<Node> new_node(ref<V> value, ref<Node> left, ref<Node> right) {
|
ref<Node> new_node(ref<V> value, ref<Node> left, ref<Node> right)
|
||||||
|
{
|
||||||
ref<Node> node = current_db->malloc<Node>();
|
ref<Node> node = current_db->malloc<Node>();
|
||||||
|
node->ref_count = 1;
|
||||||
node->sz = 1+namespace_size(left)+namespace_size(right);
|
node->sz = 1+namespace_size(left)+namespace_size(right);
|
||||||
node->value = value;
|
node->value = value;
|
||||||
node->left = left;
|
node->left = left;
|
||||||
@@ -38,63 +45,101 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
ref<Node> balanceL(ref<V> value, ref<Node> left, ref<Node> right) {
|
ref<Node> balanceL(ref<V> value, ref<Node> left, ref<Node> right)
|
||||||
|
{
|
||||||
if (right == 0) {
|
if (right == 0) {
|
||||||
if (left == 0) {
|
if (left == 0) {
|
||||||
return new_node(value);
|
return new_node(value);
|
||||||
} else {
|
} else {
|
||||||
if (left->left == 0) {
|
if (left->left == 0) {
|
||||||
if (left->right == 0) {
|
if (left->right == 0) {
|
||||||
|
left->ref_count++;
|
||||||
return new_node(value,left,0);
|
return new_node(value,left,0);
|
||||||
} else {
|
} else {
|
||||||
|
Namespace<V> new_left = new_node(left->value);
|
||||||
|
Namespace<V> new_right = new_node(value);
|
||||||
return new_node(left->right->value,
|
return new_node(left->right->value,
|
||||||
new_node(left->value),
|
new_left,
|
||||||
new_node(value));
|
new_right);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (left->right == 0) {
|
if (left->right == 0) {
|
||||||
|
Namespace<V> new_right = new_node(value);
|
||||||
|
left->left->ref_count++;
|
||||||
return new_node(left->value,
|
return new_node(left->value,
|
||||||
left->left,
|
left->left,
|
||||||
new_node(value));
|
new_right);
|
||||||
} else {
|
} else {
|
||||||
if (left->right->sz < 2 * left->left->sz) {
|
if (left->right->sz < 2 * left->left->sz) {
|
||||||
return new_node(left->value,
|
left->left->ref_count++;
|
||||||
left->left,
|
left->right->ref_count++;
|
||||||
|
Namespace<V> new_right =
|
||||||
new_node(value,
|
new_node(value,
|
||||||
left->right,
|
left->right,
|
||||||
0));
|
0);
|
||||||
|
return new_node(left->value,
|
||||||
|
left->left,
|
||||||
|
new_right);
|
||||||
} else {
|
} else {
|
||||||
return new_node(left->right->value,
|
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<V> new_left =
|
||||||
new_node(left->value,
|
new_node(left->value,
|
||||||
left->left,
|
left->left,
|
||||||
left->right->left),
|
left->right->left);
|
||||||
|
Namespace<V> new_right =
|
||||||
new_node(value,
|
new_node(value,
|
||||||
left->right->right,
|
left->right->right,
|
||||||
0));
|
0);
|
||||||
|
return new_node(left->right->value,
|
||||||
|
new_left,
|
||||||
|
new_right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (left == 0) {
|
if (left == 0) {
|
||||||
|
right->ref_count++;
|
||||||
return new_node(value,0,right);
|
return new_node(value,0,right);
|
||||||
} else {
|
} else {
|
||||||
if (left->sz > 3*right->sz) {
|
if (left->sz > 3*right->sz) {
|
||||||
if (left->right->sz < 2*left->left->sz)
|
if (left->right->sz < 2*left->left->sz) {
|
||||||
return new_node(left->value,
|
left->left->ref_count++;
|
||||||
left->left,
|
left->right->ref_count++;
|
||||||
|
right->ref_count++;
|
||||||
|
Namespace<V> new_right =
|
||||||
new_node(value,
|
new_node(value,
|
||||||
left->right,
|
left->right,
|
||||||
right));
|
right);
|
||||||
else
|
return new_node(left->value,
|
||||||
return new_node(left->right->value,
|
left->left,
|
||||||
|
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<V> new_left =
|
||||||
new_node(left->value,
|
new_node(left->value,
|
||||||
left->left,
|
left->left,
|
||||||
left->right->left),
|
left->right->left);
|
||||||
|
Namespace<V> new_right =
|
||||||
new_node(value,
|
new_node(value,
|
||||||
left->right->right,
|
left->right->right,
|
||||||
right));
|
right);
|
||||||
|
return new_node(left->right->value,
|
||||||
|
new_left,
|
||||||
|
new_right);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
left->ref_count++;
|
||||||
|
right->ref_count++;
|
||||||
return new_node(value,left,right);
|
return new_node(value,left,right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,15 +147,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
ref<Node> balanceR(ref<V> value, ref<Node> left, ref<Node> right) {
|
ref<Node> balanceR(ref<V> value, ref<Node> left, ref<Node> right)
|
||||||
|
{
|
||||||
if (left == 0) {
|
if (left == 0) {
|
||||||
if (right == 0) {
|
if (right == 0) {
|
||||||
return new_node(value);
|
return new_node(value);
|
||||||
} else {
|
} else {
|
||||||
if (right->left == 0) {
|
if (right->left == 0) {
|
||||||
if (right->right == 0) {
|
if (right->right == 0) {
|
||||||
|
right->ref_count++;
|
||||||
return new_node(value,0,right);
|
return new_node(value,0,right);
|
||||||
} else {
|
} else {
|
||||||
|
right->right->ref_count++;
|
||||||
Namespace<V> new_left =
|
Namespace<V> new_left =
|
||||||
new_node(value);
|
new_node(value);
|
||||||
return new_node(right->value,
|
return new_node(right->value,
|
||||||
@@ -128,6 +176,8 @@ public:
|
|||||||
new_right);
|
new_right);
|
||||||
} else {
|
} else {
|
||||||
if (right->left->sz < 2 * right->right->sz) {
|
if (right->left->sz < 2 * right->right->sz) {
|
||||||
|
right->left->ref_count++;
|
||||||
|
right->right->ref_count++;
|
||||||
Namespace<V> new_left =
|
Namespace<V> new_left =
|
||||||
new_node(value,
|
new_node(value,
|
||||||
0,
|
0,
|
||||||
@@ -136,6 +186,11 @@ public:
|
|||||||
new_left,
|
new_left,
|
||||||
right->right);
|
right->right);
|
||||||
} else {
|
} 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<V> new_left =
|
Namespace<V> new_left =
|
||||||
new_node(value,
|
new_node(value,
|
||||||
0,
|
0,
|
||||||
@@ -153,10 +208,14 @@ public:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (right == 0) {
|
if (right == 0) {
|
||||||
|
left->ref_count++;
|
||||||
return new_node(value,left,0);
|
return new_node(value,left,0);
|
||||||
} else {
|
} else {
|
||||||
if (right->sz > 3*left->sz) {
|
if (right->sz > 3*left->sz) {
|
||||||
if (right->left->sz < 2*right->right->sz) {
|
if (right->left->sz < 2*right->right->sz) {
|
||||||
|
left->ref_count++;
|
||||||
|
right->left->ref_count++;
|
||||||
|
right->right->ref_count++;
|
||||||
Namespace<V> new_left =
|
Namespace<V> new_left =
|
||||||
new_node(value,
|
new_node(value,
|
||||||
left,
|
left,
|
||||||
@@ -165,6 +224,12 @@ public:
|
|||||||
new_left,
|
new_left,
|
||||||
right->right);
|
right->right);
|
||||||
} else {
|
} 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<V> new_left =
|
Namespace<V> new_left =
|
||||||
new_node(value,
|
new_node(value,
|
||||||
left,
|
left,
|
||||||
@@ -175,10 +240,11 @@ public:
|
|||||||
right->right);
|
right->right);
|
||||||
return new_node(right->left->value,
|
return new_node(right->left->value,
|
||||||
new_left,
|
new_left,
|
||||||
new_right
|
new_right);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
left->ref_count++;
|
||||||
|
right->ref_count++;
|
||||||
return new_node(value,left,right);
|
return new_node(value,left,right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,13 +273,20 @@ Namespace<V> namespace_insert(Namespace<V> map, ref<V> value)
|
|||||||
int cmp = textcmp(&value->name,&map->value->name);
|
int cmp = textcmp(&value->name,&map->value->name);
|
||||||
if (cmp < 0) {
|
if (cmp < 0) {
|
||||||
Namespace<V> left = namespace_insert(map->left, value);
|
Namespace<V> left = namespace_insert(map->left, value);
|
||||||
return Node<V>::balanceL(map->value,left,map->right);
|
Namespace<V> node = Node<V>::balanceL(map->value,left,map->right);
|
||||||
|
namespace_release(left);
|
||||||
|
return node;
|
||||||
} else if (cmp > 0) {
|
} else if (cmp > 0) {
|
||||||
Namespace<V> right = namespace_insert(map->right, value);
|
Namespace<V> right = namespace_insert(map->right, value);
|
||||||
return Node<V>::balanceR(map->value, map->left, right);
|
Namespace<V> node = Node<V>::balanceR(map->value, map->left, right);
|
||||||
} else
|
namespace_release(right);
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
map->left->ref_count++;
|
||||||
|
map->right->ref_count++;
|
||||||
return Node<V>::new_node(value,map->left,map->right);
|
return Node<V>::new_node(value,map->left,map->right);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <class V>
|
template <class V>
|
||||||
ref<V> namespace_lookup(Namespace<V> map, PgfText *name)
|
ref<V> namespace_lookup(Namespace<V> map, PgfText *name)
|
||||||
@@ -256,4 +329,18 @@ void namespace_iter(Namespace<V> map, PgfItor* itor, PgfExn *err)
|
|||||||
if (err->type != PGF_EXN_NONE)
|
if (err->type != PGF_EXN_NONE)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class V>
|
||||||
|
void namespace_release(Namespace<V> node)
|
||||||
|
{
|
||||||
|
if (node == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(--node->ref_count)) {
|
||||||
|
namespace_release(node->left);
|
||||||
|
namespace_release(node->right);
|
||||||
|
DB::free(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -154,7 +154,9 @@ Namespace<V> PgfReader::read_namespace(ref<V> (PgfReader::*read_value)())
|
|||||||
Namespace<V> nmsp = 0;
|
Namespace<V> nmsp = 0;
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
ref<V> value = (this->*read_value)();
|
ref<V> value = (this->*read_value)();
|
||||||
nmsp = namespace_insert(nmsp, value);
|
Namespace<V> new_nmsp = namespace_insert(nmsp, value);
|
||||||
|
namespace_release(nmsp);
|
||||||
|
nmsp = new_nmsp;
|
||||||
}
|
}
|
||||||
return nmsp;
|
return nmsp;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user